<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 Jun 5, 2016, at 9:40 PM, Andrew Bennett &lt;<a href="mailto:cacoyi@gmail.com" class="">cacoyi@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" style="font-family: Helvetica; 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;" class="">Responses inline<br class=""><div class="gmail_extra"><br class=""><div class="gmail_quote">On Mon, Jun 6, 2016 at 12:23 PM, Matthew Johnson<span class="Apple-converted-space">&nbsp;</span><span dir="ltr" class="">&lt;<a href="mailto:matthew@anandabits.com" target="_blank" class="">matthew@anandabits.com</a>&gt;</span><span class="Apple-converted-space">&nbsp;</span>wrote:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div dir="auto" class=""><div class=""><span class=""></span></div><div class=""><div class=""><br class=""><br class="">Sent from my iPad</div><span class=""><div class=""><br class="">On Jun 5, 2016, at 8:43 PM, Andrew Bennett &lt;<a href="mailto:cacoyi@gmail.com" target="_blank" class="">cacoyi@gmail.com</a>&gt; wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class="">Thanks Matthew, my responses are inline:<br class=""><div class="gmail_extra"><br class=""><div class="gmail_quote">On Mon, Jun 6, 2016 at 10:32 AM, Matthew Johnson<span class="Apple-converted-space">&nbsp;</span><span dir="ltr" class="">&lt;<a href="mailto:matthew@anandabits.com" target="_blank" class="">matthew@anandabits.com</a>&gt;</span><span class="Apple-converted-space">&nbsp;</span>wrote:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div dir="auto" class=""><div class=""><br class=""><br class="">Sent from my iPad</div><span class=""><div class=""><br class="">On Jun 5, 2016, at 6:50 PM, Andrew Bennett &lt;<a href="mailto:cacoyi@gmail.com" target="_blank" class="">cacoyi@gmail.com</a>&gt; wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class="">Perhaps I was unclear, in my explanation.&nbsp;The guarantee I'm enforcing is that the closure is called exactly once before being released.<div class=""><br class=""></div><div class="">Everything I suggested is a compile-time check.</div><div class=""><br class=""></div><div class="">The compile-time warning and runtime `fatalError` I suggested could be replaced with a compile-time error, however even in this case it is still statically checked for the warning.</div><div class=""><br class=""></div>The compiler can statically guarantee<span class="Apple-converted-space">&nbsp;</span><b class="">exactly one</b><span class="Apple-converted-space">&nbsp;</span>of these things happens in methods using the closure:<br class=""><div class=""><div class=""><ul class=""><li class="">the closure is<span class="Apple-converted-space">&nbsp;</span><b class="">called</b></li><li class="">the closure is<span class="Apple-converted-space">&nbsp;</span><b class="">stored</b></li><li class="">the closure is<span class="Apple-converted-space">&nbsp;</span><b class="">passed</b><span class="Apple-converted-space">&nbsp;</span>to another method</li><li class="">the program&nbsp;<b class="">aborts</b><span class="Apple-converted-space">&nbsp;</span>with something like a fatalError</li></ul><div class="">If the closure is stored then there must be a<span class="Apple-converted-space">&nbsp;</span><b class="">deinit</b>, and those checks apply there as well.</div><div class=""><br class=""></div><div class="">I believe this is sufficient to ensure the closure is called once. Please let me know if there are any cases these checks miss.</div></div></div></div></div></blockquote><div class=""><br class=""></div></span><div class="">If the closure is stored in a member it could be called in the implementation of any other member.&nbsp; Calls to other members could come from arbitrary locations in the surrounding program at arbitrary points in time (unless you have static analysis that can prove a narrower set of possibilities).</div></div></blockquote><div class="">&nbsp;</div><div class="">This isn't a problem if the member has to have the type annotation, all uses of the member, whether from elsewhere in the program, or other methods, would have to pass the checks.</div><div class=""><br class=""></div><div class="">If you call the closure you must nil/replace the member.</div></div></div></div></div></blockquote><div class=""><br class=""></div></span>Ok, so the member must be an optional?&nbsp; If that is the idea I would suggest considering something similar to 'weak' where it automatically gets set to nil after it is called (which could maybe become a property behavior in the future).</div></div></blockquote><div class="">&nbsp;</div><div class="">That's a great idea, auto-nilling would work well. I was also thinking it should be possible to replace an existing non-optional stored closure if you call the old one in the old scope (see the&nbsp;<span style="font-family: Menlo; font-size: 11px;" class="">callClosure</span>&nbsp;method in my previous post). However auto-nilling could simplify the concept.</div><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div dir="auto" class=""><div class=""><br class=""></div><div class="">I don't think you mentioned the case of reassigning the member when it is non-nil.&nbsp; You would have to require users to verify it is nil before setting it or if it is not nil, calling it before assigning to it.<br class=""><div class=""><span class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div dir="auto" class=""><div class="">And if you have a model that relies on behavior in a deinit then storing the closure won't be possible for structs.</div></div></blockquote><div class="">&nbsp;</div><div class="">This is true, considering you don't want to copy a @once closure you probably don't want value-type semantics anyway.</div></div></div></div></div></blockquote><div class=""><br class=""></div></span><div class="">That's a good point.&nbsp; Since we don't have control over copy behavior in Swift it wouldn't make sense at all unless / until we can make structs that have move semantics (maybe if / when we get a Rust-like ownership system?).</div></div></div></div></blockquote><div class="">Interesting, thanks, I wasn't aware of Rust's ownership concept - I've been working on a related proposal for Swift.</div></div></div></div></div></blockquote><div><br class=""></div><div>Rust is really leading the way here in bringing linear types into a mainstream language. &nbsp;Getting it right isn’t easy. &nbsp;Rust’s system has evolved quite a bit over the years since they began. &nbsp;It will be good to learn as much as possible from Rust (both what it gets right and also areas that could maybe be improved).&nbsp;</div><div><br class=""></div><div>If you have a draft of anything and would like feedback feel free to send me a link (on or off list). &nbsp;I have a lot of interest in this area as well.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family: Helvetica; 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;" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div dir="auto" class=""><div class=""><div class=""><span class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div dir="auto" class=""><div class="">You have also missed the case that the closure is captured by another closure (maybe it is a completion block and you call it in a completion block of a method your method calls).</div></div></blockquote><div class="">&nbsp;</div><div class="">This is correct. I forgot to mention that I'm sorry, thanks for pointing it out!</div><div class=""><br class=""></div><div class="">I was thinking that a @once closure can only be captured by another @once closure. We can add that as another dot-point:</div><div class=""><br class=""></div><div class=""><div class=""><ul class=""><li class="">the closure is captured by another @once closure, this is the only time it can be captured.<br class=""></li></ul></div></div></div></div></div></div></blockquote></span><div class="">I like the idea behind this proposal in theory.&nbsp; However, it really seems to cry out for linear types.&nbsp; I have a feeling we would end up with a better (and more general) solution if Swift goes down that path in the future.&nbsp; At minimum, I would like to hear input from those who work on the type system.&nbsp; If a more robust, less ad-hoc solution will be possible in the future it might be best to wait.</div><div class=""><br class=""></div><div class="">On the other hand, completion callbacks that require this guarantee are pretty common.&nbsp; The semantic is part of the contract whether we have language support for it or not.&nbsp; Maybe we can do something now that could be subsumed by a more general feature in the future...</div><div class=""><div class="h5"><div class=""><br class=""></div></div></div></div></div></div></blockquote><div class="">I have the same thinking, I'd like the semantics now, and as as strongly as the language can allow. If the language gets better type support then we get better or less restrictive assurances.</div><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div dir="auto" class=""><div class=""><div class=""><div class=""><div class="h5"><div class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">&nbsp;</div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div dir="auto" class=""><div class=""><div class=""><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div class="gmail_extra"><br class=""><div class="gmail_quote">On Sun, Jun 5, 2016 at 11:59 PM, Matthew Johnson<span class="Apple-converted-space">&nbsp;</span><span dir="ltr" class="">&lt;<a href="mailto:matthew@anandabits.com" target="_blank" class="">matthew@anandabits.com</a>&gt;</span><span class="Apple-converted-space">&nbsp;</span>wrote:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div dir="auto" class=""><div class=""><br class=""><br class="">Sent from my iPad</div><span class=""><div class=""><br class="">On Jun 5, 2016, at 8:52 AM, Andrew Bennett &lt;<a href="mailto:cacoyi@gmail.com" target="_blank" class="">cacoyi@gmail.com</a>&gt; wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class="">Storing into a member would be fine, as long as it must keep&nbsp;<span style="color: rgb(187, 44, 162); font-family: Menlo; font-size: 11px;" class="">@once</span>&nbsp;as a type annotation and the compiler makes sure you maintain:<div class=""><span style="font-family: Menlo; font-size: 11px;" class="">&nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>sum</span><font face="monospace, monospace" class="">(callCount, storeCount, passCount) == 1</font><div class=""><br class=""></div><div class="">For example:</div><div class="">&nbsp;&nbsp;<span style="color: rgb(187, 44, 162); font-family: Menlo; font-size: 11px;" class="">class&nbsp;</span><span style="font-family: Menlo; font-size: 11px;" class="">Example {</span><br class=""><div class=""><span style="color: rgb(187, 44, 162); font-family: Menlo; font-size: 11px;" class="">&nbsp; &nbsp;&nbsp;</span><span style="color: rgb(187, 44, 162); font-family: Menlo; font-size: 11px;" class="">private<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(187, 44, 162); font-family: Menlo; font-size: 11px;" class="">var&nbsp;</span><span style="font-family: Menlo; font-size: 11px;" class="">closure: (</span><span style="color: rgb(187, 44, 162); font-family: Menlo; font-size: 11px;" class="">@once</span><span style="font-family: Menlo; font-size: 11px;" class="">&nbsp;(</span><span style="font-family: Menlo; font-size: 11px;" class="">T) -&gt;&nbsp;</span><span style="font-family: Menlo; font-size: 11px;" class="">Void)?</span></div><div class=""><span style="font-family: Menlo; font-size: 11px;" class=""><br class=""></span></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp;&nbsp;</span><span style="color: rgb(187, 44, 162);" class="">func</span><span class=""><span class="Apple-converted-space">&nbsp;</span>callClosure(value:<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(112, 61, 170);" class="">T,&nbsp;</span>replace<span style="color: rgb(112, 61, 170);" class="">:&nbsp;</span>(<span style="color: rgb(187, 44, 162);" class="">@once</span>&nbsp;(T) -&gt;&nbsp;Void)? =&nbsp;<span style="color: rgb(187, 44, 162);" class="">nil</span>) {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp; &nbsp;&nbsp;</span><span style="color: rgb(0, 132, 0);" class="">// the compiler should error if it detects the closure:</span></div><div style="margin: 0px; line-height: normal;" class=""><font color="#008400" style="font-family: Menlo; font-size: 11px;" class="">&nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>// &nbsp;* escaping more than once, while still being&nbsp;</font><font color="#008400" face="Menlo" class=""><span style="font-size: 11px;" class="">stored,</span></font></div><div style="margin: 0px; line-height: normal;" class=""><font color="#008400" face="Menlo" class=""><span style="font-size: 11px;" class="">&nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>//&nbsp;</span></font><span style="color: rgb(0, 132, 0); font-family: Menlo; font-size: 11px;" class="">&nbsp;*</span><span style="color: rgb(0, 132, 0); font-family: Menlo; font-size: 11px;" class="">&nbsp;</span><span style="font-size: 11px; color: rgb(0, 132, 0); font-family: Menlo;" class="">or being called while still being stored or escaping,</span></div><div style="margin: 0px; line-height: normal;" class=""><font color="#008400" face="Menlo" class=""><span style="font-size: 11px;" class="">&nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>//&nbsp;</span></font><span style="color: rgb(0, 132, 0); font-family: Menlo; font-size: 11px;" class="">&nbsp;*</span><span style="color: rgb(0, 132, 0); font-family: Menlo; font-size: 11px;" class="">&nbsp;</span><span style="font-size: 11px; color: rgb(0, 132, 0); font-family: Menlo;" class="">or being overwritten without being called</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(187, 44, 162);" class="">if</span><span class=""><span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(187, 44, 162);" class="">let</span><span class=""><span class="Apple-converted-space">&nbsp;</span>closure =<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(187, 44, 162);" class="">self</span><span class="">.closure {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(187, 44, 162);" class="">self</span><span class="">.closure =&nbsp;</span>replace</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>closure(value)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>}</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>}</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span class=""></span><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(187, 44, 162);" class="">deinit</span><span class=""><span class="Apple-converted-space">&nbsp;</span>{</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp; &nbsp;&nbsp;</span><span style="color: rgb(0, 132, 0);" class="">// compiler warning: that closure is potentially un-called</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="color: rgb(0, 132, 0);" class="">&nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>// runtime fatalError if it's .Some(Closure) after deinit</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>}</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp;<span class="Apple-converted-space">&nbsp;</span>}</span></div></div><div class=""><br class=""></div><div class="">There could be a standard library type with those guarantees built in.</div></div></div></div></div></blockquote><div class=""><br class=""></div></span><div class="">I don't consider this compiler verification.&nbsp; It is runtime verification.&nbsp; The best the compiler can do is enforce constraints that allow for guaranteed runtime verification.&nbsp; You can argue that is better than nothing but it is not a static guarantee of correct behavior.</div><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><div class=""><div class=""><br class=""></div></div></div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Sun, Jun 5, 2016 at 10:12 PM, Matthew Johnson<span class="Apple-converted-space">&nbsp;</span><span dir="ltr" class="">&lt;<a href="mailto:matthew@anandabits.com" target="_blank" class="">matthew@anandabits.com</a>&gt;</span><span class="Apple-converted-space">&nbsp;</span>wrote:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div dir="auto" class=""><div class=""><br class=""><br class="">Sent from my iPad</div><span class=""><div class=""><br class="">On Jun 5, 2016, at 6:56 AM, Andrew Bennett &lt;<a href="mailto:cacoyi@gmail.com" target="_blank" class="">cacoyi@gmail.com</a>&gt; wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class="">I like this.<div class=""><br class=""></div><div class="">One of the suggestions on @noescape(once) was that it just becomes @once and works with escaping closures too. It might be possible if compile time checks verified that the closure isn't copied, and that it is called before being deinit-ialized. Failing that I'm happy with a runtime circumstance in the cases the compiler can't check.</div></div></div></blockquote><div class=""><br class=""></div></span>Yeah, maybe if it is only used asynchronously and never stored in a member or global it could be verified and that is a pretty common case.&nbsp; That would certainly be easier than the general case.<div class=""><br class=""></div><div class=""><div class="">I prefer @once over @required if the guarantee is single execution.&nbsp; If the guarantee is *at least once* obviously @once is not the right attribute, but I'm not convinced @required is either.&nbsp; Maybe @invoked.</div><div class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><br class=""></div><div class="">It would be great if @required took into the account the feedback from that proposal and considered the synchronous case too.</div><div class=""><br class=""></div><div class="">As an aside, you can get some of the guarantees you want like this:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="color: rgb(187, 44, 162);" class="">func</span><span class=""><span class="Apple-converted-space">&nbsp;</span>doSomething(completionHandler: (</span><span style="color: rgb(79, 129, 135);" class="">SomeEnum</span><span class="">) -&gt; ()) {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(61, 29, 129);" class=""><span style="" class="">&nbsp;<span class="Apple-converted-space">&nbsp;</span></span><span class="">dispatch_async</span><span style="" class="">(</span><span style="color: rgb(79, 129, 135);" class="">someQueue</span><span style="" class="">) {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(187, 44, 162);" class="">let</span><span class=""><span class="Apple-converted-space">&nbsp;</span>result:<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(79, 129, 135);" class="">SomeEnum</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="" class="">&nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0, 132, 0);" class="">// the compiler ensures 'result' is set</span><span style="color: rgb(79, 129, 135);" class=""><br class=""></span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(187, 44, 162);" class="">defer</span><span class=""><span class="Apple-converted-space">&nbsp;</span>{ completionHandler(result) }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class=""><br class=""></span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class=""><span style="" class="">&nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(187, 44, 162);" class="">if</span><span style="" class=""><span class="Apple-converted-space">&nbsp;</span></span><span class="">aCondition</span><span style="" class=""><span class="Apple-converted-space">&nbsp;</span>{</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class=""><span style="" class="">&nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(187, 44, 162);" class="">if</span><span style="" class=""><span class="Apple-converted-space">&nbsp;</span></span><span class="">bCondition</span><span style="" class=""><span class="Apple-converted-space">&nbsp;</span>{</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>result = .</span><span style="color: rgb(49, 89, 93);" class="">Foo</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>}<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(187, 44, 162);" class="">else</span><span class=""><span class="Apple-converted-space">&nbsp;</span>{</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>result = .</span><span style="color: rgb(49, 89, 93);" class="">Bar</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>}</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="" class="">&nbsp; &nbsp; &nbsp;&nbsp;</span><span class="">// the compiler ensures you do this, because it is 'let'</span></div><p style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""></p><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(187, 44, 162);" class="">return</span></div><div class=""><span style="font-family: Menlo; font-size: 11px;" class="">&nbsp; &nbsp;&nbsp;</span><span style="font-family: Menlo; font-size: 11px;" class="">}</span><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class=""><br class=""></span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class=""><span style="" class="">&nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(187, 44, 162);" class="">if</span><span style="" class=""><span class="Apple-converted-space">&nbsp;</span></span><span class="">cCondition</span><span style="" class=""><span class="Apple-converted-space">&nbsp;</span>{</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>result = .</span><span style="color: rgb(49, 89, 93);" class="">Baz</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>}</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">&nbsp;<span class="Apple-converted-space">&nbsp;</span>}</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="">}</span></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Sun, Jun 5, 2016 at 9:42 PM, Matthew Johnson via swift-evolution<span class="Apple-converted-space">&nbsp;</span><span dir="ltr" class="">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt;</span><span class="Apple-converted-space">&nbsp;</span>wrote:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div dir="auto" class=""><div class=""><br class=""><br class="">Sent from my iPad</div><span class=""><div class=""><br class="">On Jun 5, 2016, at 5:02 AM, Patrick Pijnappel via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class="">This has actually been proposed before, see SE-0073:&nbsp;<a href="https://github.com/apple/swift-evolution/blob/master/proposals/0073-noescape-once.md" target="_blank" class="">https://github.com/apple/swift-evolution/blob/master/proposals/0073-noescape-once.md</a></div></div></blockquote><div class=""><br class=""></div></span>Actually that proposal was for noescape closures and this suggestion is for escaping closures.&nbsp; I don't think the compiler can verify this for noescape closures.&nbsp; If it is possible it would be far more complicated.<div class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><div class=""><br class=""></div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Sun, Jun 5, 2016 at 11:37 AM, Charles Srstka via swift-evolution<span class="Apple-converted-space">&nbsp;</span><span dir="ltr" class="">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt;</span><span class="Apple-converted-space">&nbsp;</span>wrote:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;">MOTIVATION:<br class=""><br class="">As per the current situation, there is a pitfall when writing asynchronous APIs that does not occur when writing synchronous APIs. Consider the following synchronous API:<br class=""><br class="">func doSomething() -&gt; SomeEnum {<br class="">&nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>if aCondition {<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>if bCondition {<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>return .Foo<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>} else {<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>return .Bar<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>}<br class="">&nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>} else {<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>if cCondition {<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>return .Baz<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>}<br class="">&nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>}<br class="">}<br class=""><br class="">The compiler will give an error here, since if both aCondition and cCondition are false, the function will not return anything.<br class=""><br class="">However, consider the equivalent async API:<br class=""><br class="">func doSomething(completionHandler: (SomeEnum) -&gt; ()) {<br class="">&nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>dispatch_async(someQueue) {<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>if aCondition {<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>if bCondition {<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>completionHandler(.Foo)<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>} else {<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>completionHandler(.Bar)<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>}<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>} else {<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>if cCondition {<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>completionHandler(.Baz)<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>}<br class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>}<br class="">&nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>}<br class="">}<br class=""><br class="">Whoops, now the function can return without ever firing its completion handler, and the problem might not be discovered until runtime (and, depending on the complexity of the function, may be hard to find).<br class=""><br class="">PROPOSED SOLUTION:<br class=""><br class="">Add a @required attribute that can be applied to closure arguments. This attribute simply states that the given closure will always be eventually called, and the compiler can enforce this.<br class=""><br class="">DETAILED DESIGN:<br class=""><br class="">- The @required attribute states in our API contract that a given closure *must* be called at some point after the function is called.<br class=""><br class="">- Standard API calls like dispatch_async that contractually promise to execute a closure or block get @required added to their signatures.<br class=""><br class="">- When the compiler sees a @required closure in a function declaration, it checks to make sure that every execution path either calls the closure at some point, or sends a @required closure to another API that eventually ends up calling the closure.<br class=""><br class="">- If there’s a way for a @required closure not to be called, the compiler emits an error letting the developer know about the bug in his/her code.<br class=""><br class="">IMPACT ON EXISTING CODE:<br class=""><br class="">None. This is purely additive.<br class=""><br class="">ALTERNATIVES CONSIDERED:<br class=""><br class="">I got nothin’.<br class=""><br class="">Charles<br class=""><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></blockquote></div><br class=""></div></div></div></blockquote><blockquote type="cite" class=""><div class=""><span class="">_______________________________________________</span><br class=""><span class="">swift-evolution mailing list</span><br class=""><span class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a></span><br class=""><span class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br class=""></div></blockquote></div></div></div></div><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></blockquote></div></div></div></div></div></blockquote></div></div></div></div></div></blockquote></div></div></div></blockquote></div></div></div></blockquote></div></div></div></blockquote></div></div></div></blockquote></div></div></div></div></blockquote></div></div></div></div></div></blockquote></div></div></div></div></blockquote></div><br class=""></body></html>