<div dir="ltr">&gt; The difference here is that unlike shadowing (if let foo = foo), if foo were mutable then it could still be mutated directly, no need to do it with force unwrapping.<div><br></div><div>FWIW, there is no need for force unwrapping in any case.</div><div><br></div><div><div><span class="inbox-Apple-tab-span" style="white-space:pre">                </span>var bar:Foo? = nil</div><div><br></div><div><span class="inbox-Apple-tab-span" style="white-space:pre">                </span>if let real_foo = foo {</div><div><span class="inbox-Apple-tab-span" style="white-space:pre">                        </span>bar = real_foo</div><div><span class="inbox-Apple-tab-span" style="white-space:pre">                </span>}</div><div><br></div><div><span class="inbox-Apple-tab-span" style="white-space:pre">                </span>if var bar_copy = bar {</div><div><span class="inbox-Apple-tab-span" style="white-space:pre">                        </span>bar_copy.someMutatingMethod()</div><div>                        bar = bar_copy</div><div><span class="inbox-Apple-tab-span" style="white-space:pre">                </span>}</div></div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Nov 9, 2016 at 3:28 PM Haravikk &lt;<a href="mailto:swift-evolution@haravikk.me">swift-evolution@haravikk.me</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg">On 9 Nov 2016, at 12:19, Rien &lt;<a href="mailto:Rien@balancingrock.nl" class="gmail_msg" target="_blank">Rien@balancingrock.nl</a>&gt; wrote:</div><div class="gmail_msg"><blockquote type="cite" class="gmail_msg">On 9 Nov 2016, at 06:51, David Hart &lt;<a href="mailto:david@hartbit.com" class="gmail_msg" target="_blank">david@hartbit.com</a>&gt; wrote:<br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><blockquote type="cite" class="gmail_msg"></blockquote></blockquote></blockquote><blockquote type="cite" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="gmail_msg"><blockquote type="cite" class="gmail_msg"><blockquote type="cite" class="gmail_msg"></blockquote></blockquote></blockquote></div></blockquote><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><blockquote type="cite" class="gmail_msg"><blockquote type="cite" class="gmail_msg">On 3 Nov 2016, at 20:23, Nevin Brackett-Rozinsky via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br class="gmail_msg"><br class="gmail_msg">This looks like a lot of complexity for very little gain.<br class="gmail_msg"><br class="gmail_msg">Aside from any implementation concerns, this proposal substantially increases the cognitive load on developers. To figure out what a piece of code means, someone reading it will have to mentally keep track of a “type stack” for every variable. That is the opposite of “clarity at the point of use”.<br class="gmail_msg"></blockquote></blockquote></blockquote></div><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="gmail_msg"><blockquote type="cite" class="gmail_msg"><br class="gmail_msg">Very well said. I think this is perhaps the number one complaint I have about the proposal.<br class="gmail_msg"></blockquote><br class="gmail_msg">Did you see my response to this? There should be no particular cognitive load increase; think of the feature like type inference, the idea here is that the type-checker is gaining the same knowledge that you already have, i.e- you know something isn&#39;t nil, so the type-checker should too.<br class="gmail_msg"></blockquote><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="gmail_msg"><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important" class="gmail_msg">Locally in short routines yes.</span><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="gmail_msg"><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important" class="gmail_msg">But in larger modules and non-local this does not apply.</span><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">I&#39;m not sure what you mean; type-narrowing doesn&#39;t occur across scopes, ultimately you will always have some starting type where the variable was declared as a property, function argument or local variable, and it is narrow only where it is used, and the narrowing only occurs within that scope for as long as it is relevant.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">In other words, the narrowing is always local. If you know your method takes an optional string for example then you know that that variable is still an optional string throughout that method, type-narrowing just helps to guarantee that it is nil or non-nil where you expect it to be.</div></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important" class="gmail_msg">Imo it should always be possible to look at a type declaration and -from that- derive all necessary knowledge about the type.</span><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="gmail_msg"></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">As I say, narrowing never changes the type; if you have a variable with a declared type of Foo, that is narrowed to Bar, then it is because Bar extends Foo and thus is compatible with it, giving you access to any additional methods of Bar without interfering with what you know of Foo.</div></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important" class="gmail_msg">Besides when using a narrowed type as a parameter for an optional it must be automatically be widened again? hence you would mentally keep track of the status of that variable.</span><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="gmail_msg"></div></blockquote></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"></div><br class="gmail_msg"><div class="gmail_msg">I&#39;m not sure I follow this question; do you mean something like this:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">        </span>func someMethod(foo:Foo?) {</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">                </span>var bar:Foo? = nil // bar is Optional&lt;Foo&gt;.none</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">                </span>if (foo != nil) { // foo is Optional&lt;Foo&gt;.some</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">                        </span>bar = foo // both foo and bar are Optional&lt;Foo&gt;.some</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">                </span>}</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">                </span>// both foo and bar are Optional&lt;Foo&gt; (alternative branch places no mutual guarantee on type)</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">                </span>if bar != nil { // bar is Optional&lt;Foo&gt;.some</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">                        </span>bar.someMutatingMethod()</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">                </span>}</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">        </span>}</font></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">But these are all things that the developer knows; bar can&#39;t be non-nil until a value for it is set, foo is definitely non-nil within the block etc. The only difference here is that instead of the developer having to use ! unnecessarily (or risk making a mistake) they can just use their knowledge of what it is to interact directly, as the type-checker will now also know the same thing.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">However, with the Optional&lt;T&gt; to T method shadowing issue it seems we probably will need to require a keyword, or at the very least restrict automatic narrowing to polymorphism. For optionals the code will have to look something like this:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">        </span>func someMethod(foo:Foo?) {</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">                </span>var bar:Foo? = nil</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">                </span>if unwrap foo {</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">                        </span>bar = foo</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">                </span>}</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><br class="gmail_msg"></font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">                </span>if unwrap bar {</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">                        </span>bar.someMutatingMethod()</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">                </span>}</font></div><div class="gmail_msg"><font face="Monaco" class="gmail_msg"><span class="m_-7923205845737995507Apple-tab-span gmail_msg" style="white-space:pre-wrap">        </span>}</font></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">The difference here is that unlike shadowing (if let foo = foo), if foo were mutable then it could still be mutated directly, no need to do it with force unwrapping. Of course in these simple examples you could just use the question mark operator instead, but pretend we&#39;re doing more than one thing per conditional 😉</div></div></blockquote></div>