<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 3 Nov 2016, at 08:17, Pyry Jahkola <<a href="mailto:pyry.jahkola@iki.fi" class="">pyry.jahkola@iki.fi</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="">As pleasing as it sounds*), the idea of type narrowing breaks down badly if:</div><div class=""><br class=""></div><div class="">– the binding is implicit (without explicit extra syntax involved) and</div><div class="">– what is bound happens to be mutable.</div><div class=""><br class=""></div><div class="">An example being:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class=""> <font color="#919191" class="">// <b class="">var</b> message: String?</font></font></div><div class=""><font face="Menlo" class=""> <b class="">if</b> message != <b class="">nil</b> { <font color="#919191" class="">// magic turns 'message' into a non-optional 'String' here</font></font></div><div class=""><font face="Menlo" class=""> handleMessage(message)</font></div><div class=""><font face="Menlo" class=""> message = <b class="">nil</b> <font color="#919191" class="">// 'String' is not 'ExpressibleByNilLiteral'</font></font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><br class=""></div><div class="">What magic would we require to still allow access to the Optional interface of 'message' in that block?</div></div></div></blockquote><div><br class=""></div><div>Type widening 😉</div><div><br class=""></div><div>Basically if you try to assign a value to `message` that is not valid for the narrowed type, but is fine for a wider type then it can simply be widened again at that point. You could think of the variable's type as being a stack of types, each narrower than the last; if you hit a road-block with the current type, you can try rolling back (widening) until you find one that works, at which point this is the new narrowest type, or return an error as normal.</div><div><br class=""></div><div>In this specific example you may instead think of it as re-narrowing, as after that line message can only be `nil`. </div><div><br class=""></div><div>In fact in that example we can look at it like this:</div><div><br class=""></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>// message is Optional</font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>if message != nil { // Optional.some</font></div><div></div><div></div><div></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>handleMessage(message) // Optional.some</font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>message = nil // Optional.none</font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>} // Optional.none</font></div><div><br class=""></div><div>As both branches ended with the same type, the type of message afterwards is Optional.none from that point on; allowing unwrapping operations to become invalid (as they cannot possibly succeed) and other useful behaviours. If message wasn't set to nil within the if statement then it would return to being the wider Optional (as it's the narrowest type that both branches have in common).</div></div></body></html>