<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=""><div dir="auto" 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 Nov 7, 2016, at 2:08 PM, Haravikk &lt;<a href="mailto:swift-evolution@haravikk.me" class="">swift-evolution@haravikk.me</a>&gt; 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=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On 7 Nov 2016, at 11:58, Charlie Monroe &lt;<a href="mailto:charlie@charliemonroe.net" class="">charlie@charliemonroe.net</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">I'd personally not make this automatic, but require explicit action from the developer.<div class=""><br class=""></div><div class="">In case of nullability, I have previously suggested "nonnil" keyword:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> foo: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">String</span><span style="font-variant-ligatures: no-common-ligatures;" class="">? = </span><span style="font-variant-ligatures: no-common-ligatures" class="">"Hello World"</span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">guard</span><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp;</span><span style="color: rgb(186, 45, 162);" class="">nonnil</span><span style="font-variant-ligatures: no-common-ligatures;" class="">&nbsp;</span><span style="font-variant-ligatures: no-common-ligatures; color: rgb(79, 129, 135);" class="">foo</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: rgb(186, 45, 162);" class="">else</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> {</span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; <font color="#ba2da2" class="">return</font></span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">}</span></div></div><div class=""><br class=""></div><div class="">In which way you explicitly request the type narrowing. Or:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> foo: </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">Any</span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo; color: rgb(186, 45, 162);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">guard</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">foo</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures" class="">as</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">String</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures" class="">else</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> {</span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp;&nbsp;<span style="color: rgb(186, 45, 162);" class="">return</span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">}</span></div><div class=""><br class=""></div><div class="">I.e. not using "is" which returns a boolean, but using the cast operator, which IMHO makes more sense and prevents from unintentional type narrowing…</div></div></div></div></blockquote><br class=""></div><div class="">Normally I'm a proponent of being more rather than less explicit, but the biggest draw of type-narrowing to me is that you're *already* telling the type-checker, it's really just confirming what you know automatically.</div><div class=""><br class=""></div><div class="">So if I do:</div><div class=""><br class=""></div><div class=""><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>if foo is String {</font></div><div class=""><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>// Do lots of non-string stuff</font></div><div class=""><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>(foo as String).somethingStringSpecific</font></div><div class=""><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</font></div><br class=""></div></div></blockquote><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">On the last line of the block the type-checker is able to remind me that I already know that foo is a String, so I don't need to cast it.</div><div class=""><br class=""></div><div class="">Really when it comes down to it the type-narrowing never takes anything away from you; you can always handle the value as a less specific (wider) type if you want to, but if you want to treat it like a String because you know it's one, then you can do that too.</div></div></div></blockquote><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class="">I'm concerned that if the feature had to be explicit, it would lack discoverability, and really the point is almost to get rid of the need to do things explicitly when you don't need to. It's like type inference on overdrive in a way.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">I guess I just don't see why you'd think that "guard nonnil foo" is really more explicit than "guard foo != nil", in both cases you know that foo can't be nil past that point, so is a new keyword really justified?</div></div></blockquote><br class=""></div><div>I'm simply worried a little about unwanted effects and additional compiler "cleverness". I'd simply much rather opt-in to it using a keyword or a slightly different syntax. And instead of</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span><font face="Menlo" class="">if foo is String { ... }</font></div><div><br class=""></div><div>I'd prefer</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span><font face="Menlo" class="">if foo as? String { ... }</font></div><div><br class=""></div><div>which is syntactically closer to</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span><font face="Menlo" class="">if let foo = foo as? String { ... }</font></div><div><br class=""></div><div>which is generally what we're after.</div><div><br class=""></div><div>Also, it would maintain code compatibility. The current proposal would change semantics of the code - mostly when comparing to nil.</div><div><br class=""></div><div>Xcode's migration is "nice", but I'd like to point out that migration to Swift 3 of my project took 6 hours (!) and I spent almost 2 more days manually changing what the migrator didn't manage to do on its own. And that was one of my projects. I really don't want to go through this once more.</div><div><br class=""></div><div>Not to mention the already growing non-macOS base of Swift users.</div><div><br class=""></div><div>I know now is the time for the last incompatible changes, but are the benefits of implicit type narrowing so great to warrant this?</div><div><br class=""></div></div><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""></div></body></html>