<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="">Le 4 mai 2016 à 11:55, Pyry Jahkola <<a href="mailto:pyry.jahkola@iki.fi" class="">pyry.jahkola@iki.fi</a>> a écrit :</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="">Hi Gwendal,<div class=""><br class=""></div><div class="">Nice writeup. So I see that you recognise how this extra specification will complicate (while also facilitate) things. And I also see that you're a co-author of the proposal. So I'm more than happy if you can squeeze this extra into it.</div><div class=""><br class=""></div><div class="">However reading your example code, I had to squint to see—without the compiler's squiggly red aid—what all the problematic cases are.</div><div class=""><br class=""></div><div class="">1) Is it obvious to everybody why you can't always use `x` in the end of Cases 2 and 4? For example, with `if—else` you MUST initialise the variable or escape its scope in all branches; you can't just write the following to complete the initialisation later:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class=""><span style="font-size: 11px;" class=""> let x: Int</span></font></div><div class=""><font face="Menlo" class=""><span style="font-size: 11px;" class=""> if cond { x = 1 }</span></font></div><div class=""><font face="Menlo" class=""><span style="font-size: 11px;" class=""> // ...</span></font></div><div class=""><font face="Menlo" class=""><span style="font-size: 11px;" class=""> if !cond { x = 2 } // too late!</span></font></div></div></div></blockquote><div><div><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">2) Should Cases 2 and 4 be made illegal? The requirement could then be that all `catch` blocks either:</div></div></blockquote><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class=""></div><div class="">Hello Pyry,</div><div class=""><br class=""></div></div></div></div></div><div>In case 2 and 4, you can't always use `x` at the end because there are code paths that do not initialize x.</div><div><br class=""></div><div>Let's repeat the case 2 and 4, as a reminder:</div><div><br class=""></div><div>Case 2:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// Function which rethrows closure errors:<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>func f1(closure: @noescape(once) () throws -> ()) rethrows {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>try closure()<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let x: Int<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>do {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>try f1 {<span class="Apple-tab-span" style="white-space:pre">                        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>x = try getX()<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// use x<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// use x<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>} catch {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// can't use x<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// can't use x<br class=""><br class=""></div><div>Case 4:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// Function which may throw before, inside, or after the closure:<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>func f2(closure: @noescape(once) () throws -> ()) throws {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>try mayFailBefore()<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>try closure()<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>try mayFailAfter()<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let x: Int<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>do {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>try f2 {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>x = try getX()<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// use x<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// use x<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>} catch {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// can't use x<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// can't use x<br class=""><br class=""></div><div>To better explain them, let's replace `f1` with `do`, and `f2` with a throwing function followed with do:</div><div><br class=""></div><div><div>Rewritten case 2:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let x: Int<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>do {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>do {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>x = try getX()<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// use x<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// use x<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>} catch {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// can't use x<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// can't use x<br class=""><br class=""></div><div>Rewritten case 4:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let x: Int<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>do {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>try mayFail()</div><div><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>do {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>x = try getX()<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// use x<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// use x<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>} catch {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// can't use x<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// can't use x<br class=""><br class=""></div><div>The examples above are already the behavior of the Swift compiler. I expect @noescape(once) closures to behave the same (the cases 2 and 4 above)</div></div><div><br class=""></div><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">3) If you consider including this addition to the proposal, it might also help other reviewers if you explained how the compiler will be able to help the programmer write a valid program. E.g. what would the error messages about partially initialised variables look like? And where and when would they appear? Could the compiler suggest certain fixits? Etc.</div></div></blockquote><div><br class=""></div><div>For error messages about partially initialized variables, we just use the regular messages that we already have: `Constant 'x' used before being initialized` error.</div><div><br class=""></div><div>Gwendal Roué</div></div></body></html>