<div dir="ltr"><div>Thanks everyone for joining the discussion, I&#39;m glad that other people are thinking about this too. I should have mentioned up-front, in case it was unclear, I think this needs more discussion before it&#39;s ready as a formal proposal.</div><div><br></div><div>I think most people here seem to agree that blocks capturing objects can be a problem, and we don&#39;t want to have to type a bunch of new things to deal with it. What we&#39;re unsure of is how to deal with it.</div><div><br></div><div>The only thing I explicitly didn&#39;t agree with was that { self!.foo } is a problem because of self being weak. I think the problem here is the use of force-unwrap.</div><div><br></div><div>Also, I think that the discussion about when properties are immutable, and not necessarily being able to configure an immutable structure is a good one. It is also perhaps off-topic, except where it affects the scope of impact of this proposal. Do we agree that it&#39;s sufficient for this proposal to say that some properties could be captured as value types, and as the swift compiler gets smarter those cases will grow?</div><div><br></div><div>In Ilya&#39;s example:</div><div><div style="font-size:13px">if let computed = c?.compute() {</div><div style="font-size:13px">    print(computed)</div><div style="font-size:13px">}</div></div><div style="font-size:13px">I agree that this will change what the code does, but I think a programmer using dispatch_async will be familiar with if-statements, and so should be able to determine the implications. I think that in this case the IDE would suggest two solutions &quot;add ? to c.compute()&quot; and &quot;strongly capture c &lt;a warning about retain cycles&gt;&quot;. I think the important thing would be that the &quot;default&quot; case is that you don&#39;t have memory issues, you can&#39;t compile the code if you haven&#39;t acknowledged that with &#39;?&#39; or &#39;[strong c]&#39;.</div><div><br></div>Kevin, I think you should definitely propose that (weak in outer and inner closure), it&#39;s one of the surprises that led me to this proposal. I also really like your suggesting of requiring explicit weak/strong on self, I think this could solve many cases. What I&#39;m not sure of is whether this should be restricted to self, or the &quot;owners&quot; of the block calling method. ie.<div><br></div><div>func doWork(something: Something) {</div><div>     something.calculateSomeStuff { (a,b) in</div><div>          return self.calculate(a,b)</div><div>     }</div><div>}<br><div><br></div><div>In this case I think that strong/weak should be made explicit on &#39;something&#39; not on &#39;self&#39;.</div><div><br></div><div>I think that the main points at the moment are:</div><div> 1. The impact of requiring explicit strong/weak on self/something.</div><div> 2. How often requiring &#39;strong&#39; on *non-trivial* captures would happen.</div><div> 3. If you can mitigate most cases with small changes to APIs.</div><div><br></div><div>An example of an api change would be:</div><div><br></div><div>let data = 123</div><div>worker.doWork { [strong worker] (item: Item) in</div><div>    worker.work(data, withItem: item)</div><div>}</div><div><br></div><div>becomes:</div><div><br></div><div><div>let data = 123</div><div><div>worker.doWork { (worker: Worker, item: Item) in</div><div>    worker.work(data, withItem: item)</div><div>}</div></div></div><div><br></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Dec 9, 2015 at 6:28 AM, Kevin Ballard via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><u></u>




<div><span class=""><div>On Tue, Dec 8, 2015, at 07:55 AM, Joe Groff via swift-evolution wrote:<br></div>
<blockquote type="cite"><div>One reason cycles are so prevalent with closures is that it&#39;s easy to capture too much, since referencing &#39;self.foo&#39; always captures the entirety of &#39;self&#39;. If the properties of &#39;self&#39; you need are immutable, or you don&#39;t need to see their mutations, you can reduce the risk of cycles by capturing those properties explicitly, turning this:<br></div>
<div> </div>
<blockquote style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:40px;border-top-style:none;border-right-style:none;border-bottom-style:none;border-left-style:none;border-top-width:initial;border-right-width:initial;border-bottom-width:initial;border-left-width:initial;border-top-color:initial;border-right-color:initial;border-bottom-color:initial;border-left-color:initial;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px"><div>self.setCallback { doStuffWith(self.zim, self.zang) }<br></div>
</blockquote><div> </div>
<div>into:<br></div>
<div> </div>
<blockquote style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:40px;border-top-style:none;border-right-style:none;border-bottom-style:none;border-left-style:none;border-top-width:initial;border-right-width:initial;border-bottom-width:initial;border-left-width:initial;border-top-color:initial;border-right-color:initial;border-bottom-color:initial;border-left-color:initial;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px"><div>self.setCallback {[zim, zang] in doStuffWith(zim, zang) }<br></div>
<div> </div>
</blockquote><div>For &#39;let&#39; properties of classes, it&#39;d be reasonable to propose having closures capture the *property* directly by default in this way instead of capturing &#39;self&#39; (and possibly allowing referencing them without &#39;self.&#39;, since &#39;self&#39; wouldn&#39;t be involved in any cycle formed this way).<br></div>
</blockquote><div> </div>
</span><div>Interesting idea, but I&#39;m concerned that this would be surprising and open up a different class of bug, where properties of self unexpectedly outlive self even though they were never referenced without going through self. This can be a problem if self has a deinit that does relevant work, or if the values of the properties themselves depend on self somehow. As a trivial example, a property of self might contain an unowned reference back to self, because it knows it will never outlive self, at least until this rule is introduced and causes a dispatch_async() to access the unowned reference after self has deinited.<br></div>
<div> </div>
<div>Personally, I&#39;m happy with just using an explicit capture list for my properties if I don&#39;t want to capture self. Using this along with the practice of always omitting the `self.` whenever possible means the compiler yells at me if I accidentally capture self in an escaping closure (e.g. when I try and use a method/property without the `self.`), forcing me to make a decision there about whether I want to capture self or add a capture list for the property.<br></div>
<div> </div>
<div>Another alternative is to require an explicit capture list to capture self in an escaping closure, so you have to say `[self]` or `[weak self]`. This way you&#39;re forced to make a decision always. Potential downsides I can think of:<br></div>
<div> </div>
<div>1. It&#39;s verbose. Application code often has a lot of escaping closures, and most of them probably don&#39;t have capture lists, so that&#39;s a lot of capture lists to add.<br></div>
<div>2. It&#39;s still possible to accidentally capture self without realizing it by use of a local nested function that is itself captured. Of course, this is the same scenario that lets you capture self without even writing `self.` since local nested functions allow you to omit the `self.`, so it&#39;s already a known issue.<br></div>
<div>3. How does this interact with captures of self from enclosing closures? Right now, if I have `{ [weak self] in foo({ /* self is still weak here */ }) }`; does the inner closure need a capture list or not? How about if the outer capture is strong? `{ [self] in foo({ /* self is strong here */ }) }`? Of course, this rule would fix the current hazard of weakly capturing self at the wrong level, e.g. `{ foo({ [weak self] in ... }) }` where self is strongly captured in the outer closure, which seems to surprise people. Although now that I think of it, I&#39;ll probably submit a proposal to change that, so the outer closure captures self weakly if it&#39;s only capturing it at all because of a weak capture in a nested closure.<br></div>
<div> </div>
<div>-Kevin Ballard<br></div>

<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=pQw7h83fWt3LLbgkfL4TSUL0weaZnVFZxDe5GShw4uR09vXkg-2FD0jkoNEhuWJNnKHhe5wg9bEtNSmQdaZkosLcKCmIli4gnEnrsjxU2WeNnJay2dLkLjHtKN6-2BYSAuVTXzr8V-2FcZlScoB03T-2F1cq-2FBHeJmlJHjxlhJjgdleJTOa9Niw0BQf29NGk8r05Iekbmel9-2FuDxPxKDc652yj8VraJ0sNpqFnQeq-2FBjIVhPs3o-3D" alt="" width="1" height="1" border="0" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important">
</div>


<br>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div>