<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 class="">Normally in guard and if condition lists, you look up a value in a dictionary and conditionally cast:</div><div class=""><br class=""></div><div class=""> if let value = dict[key] as? T, ...</div><div class=""><br class=""></div><div class="">The "as?" operator passes the Any? type through, and the lhs result is T, not T?.</div><div class=""><br class=""></div><div class="">* dict[key] returns Any?</div><div class="">* Any? as T returns T?, not T??</div><div class="">* the conditional binding binds T? to T</div><div class="">* PROFIT!</div><div class=""><br class=""></div><div class="">However, this (somewhat illogical) "sugar" doesn't happen when you conditionally cast T? to U, for example, when a dictionary is [AnyHashable: String]:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 16px; 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=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> value = </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">dict</span><span style="font-variant-ligatures: no-common-ligatures" class="">[</span><span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">"Key"</span><span style="font-variant-ligatures: no-common-ligatures" class="">] </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">as</span><span style="font-variant-ligatures: no-common-ligatures" class="">? </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">NSString</span></div><div style="margin: 0px; font-size: 16px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">else</span><span style="font-variant-ligatures: no-common-ligatures" class=""> { </span><span style="font-variant-ligatures: no-common-ligatures; color: #3e1e81" class="">fatalError</span><span style="font-variant-ligatures: no-common-ligatures" class="">() }</span></div></div><div class=""><br class=""></div><div class="">(see <a href="http://i.imgur.com/SkXkk6o.jpg" class="">http://i.imgur.com/SkXkk6o.jpg</a>)</div><div class=""><br class=""></div><div class=""><div class="">* dict[key] returns String?</div><div class="">* String? as T is guaranteed to fail</div><div class=""><br class=""></div></div><div class="">In this case, the compiler asserts that a cast from String? to an unrelated type NSString always fails. You can mitigate this by sticking an "Any" cast in the middle:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 16px; 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=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> value = </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">dict</span><span style="font-variant-ligatures: no-common-ligatures" class="">[</span><span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">"Key"</span><span style="font-variant-ligatures: no-common-ligatures" class="">] </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">as</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">Any</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">as</span><span style="font-variant-ligatures: no-common-ligatures" class="">? </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">NSString</span></div><div style="margin: 0px; font-size: 16px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">else</span><span style="font-variant-ligatures: no-common-ligatures" class=""> { </span><span style="font-variant-ligatures: no-common-ligatures; color: #3e1e81" class="">fatalError</span><span style="font-variant-ligatures: no-common-ligatures" class="">() }</span></div></div><div class=""><br class=""></div><div class="">If that's not "magic", I don't know what is. (You can also cast the dictionary to [AnyHashable: NSString], etc.)</div><div class=""><br class=""></div><div class="">Jack L's initial response: "oh, that's a weird bridging edge case 😕 it seems like we should just make that work..." <a href="http://twitter.com/_jackhl/status/784998768898744320" class="">http://twitter.com/_jackhl/status/784998768898744320</a>) but he asked me to follow up here on SwiftEv. It seems to me that in conditional binding with conditional casting, you're asking the compiler to do not one but *two* magical things:</div><div class=""><br class=""></div><div class="">1. Apply what *looks* like assignment (I have a similar issue with if case/guard case) but is actually something else</div><div class="">2. Apply what *looks* like conditional casting but which magically passes Any? through to T?, not T??</div><div class=""><br class=""></div><div class="">I handwave this (but just the moment) and say "it's not really an assignment, so it's not really a conditional cast". Jack asked me to bring this discussion over to Swift Evolution and ask the greater community whether Swift is doing these things right, and if not, how it should fix them. </div><div class=""><br class=""></div><div class="">Where I stand:</div><div class=""><br class=""></div><div class="">* If there's going to be magic, it should be documented (and it is not) in the Swift Programming Language</div><div class="">* If there's going to be magic, it should work for T?, not just Any?</div><div class="">* I'd rather there not be magic here</div><div class=""><br class=""></div><div class="">-- E</div><div class="">p.s. I'd also rather that if-case/guard-case would use ":" like in switch statements not "=", but no one seems to be responding to that thread, dagnabit</div></body></html>