<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 Aug 25, 2016, at 11:56 AM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">On Thu, Aug 25, 2016 at 11:28 AM, Matthew Johnson <span dir="ltr" class="">&lt;<a href="mailto:matthew@anandabits.com" target="_blank" class="">matthew@anandabits.com</a>&gt;</span> wrote:<br class=""><div class="gmail_extra"><div class="gmail_quote"><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=""><br class=""><div class=""><div class=""><div class="h5"><blockquote type="cite" class=""><div class="">On Aug 25, 2016, at 11:15 AM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class=""><div class=""><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">On Thu, Aug 25, 2016 at 10:07 AM, Matthew Johnson<span class="">&nbsp;</span><span dir="ltr" class="">&lt;<a href="mailto:matthew@anandabits.com" target="_blank" class="">matthew@anandabits.<wbr class="">com</a>&gt;</span><span class="">&nbsp;</span>wrote:<br class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><br class=""><div class=""><span class=""><blockquote type="cite" class=""><div class="">On Aug 25, 2016, at 9:37 AM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class=""><div class=""><div dir="ltr" class=""><div style="white-space:pre-wrap" class="">Charles clarified that indeed he was pitching casting operators that match subclasses.<br class=""></div></div></div></blockquote><div class=""><br class=""></div></span><div class="">Ok, I missed that.</div><span class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div style="white-space:pre-wrap" class=""><br class="">If the compiler knows that a class is sealed, why do you think there's a new keyword needed for the compiler to prove exhaustiveness?</div></div></div></blockquote><div class=""><br class=""></div></span><div class="">I said I wasn’t sure if there was a different / better way to do it.&nbsp; Just that this *would* do it.</div><span class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div style="white-space:pre-wrap" class=""><br class=""></div><div style="white-space:pre-wrap" class="">First, you can already match exact types by writing `type(of: instance) == Base.self` (which doesn't evaluate to true if instance is of a subclass of Base).</div></div></div></blockquote><div class=""><br class=""></div></span><div class="">This might be an alternative if the compiler adds special knowledge of this syntax to prove exhaustiveness.</div></div></div></blockquote><div class=""><br class=""></div><div class="">I might be in favor of that. As it is, I can write this:</div><div class=""><br class=""></div><div class="">```</div><div class=""><div class="">func ~= &lt;T, U&gt;(lhs: T.Type, rhs: U.Type) -&gt; Bool {</div><div class="">&nbsp; return lhs == rhs</div><div class="">}</div><div class=""><br class=""></div><div class=""><div class="">class Base {</div><div class="">&nbsp; init() { }</div><div class="">}</div><div class="">class A1 : Base { }</div><div class="">class A2 : Base { }</div><div class=""><br class=""></div><div class="">let a = A1()</div></div><div class=""><br class=""></div><div class="">switch type(of: a) {</div><div class="">case A1.self:</div><div class="">&nbsp; print(1)</div><div class="">case A2.self:</div><div class="">&nbsp; print(2)</div><div class="">case Base.self:</div><div class="">&nbsp; print(0)</div><div class="">default:</div><div class="">&nbsp; fatalError()</div><div class="">}</div></div><div class="">```</div><div class=""><br class=""></div><div class="">It'd be nice if the compiler would know about exhaustiveness (and if I didn't have to define my own `~=`). This is, afaict, doable without any additional syntax in the language.</div><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><span class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div style="white-space:pre-wrap" class=""></div><div style="white-space:pre-wrap" class="">Second, if your class hierarchy is Base &gt; A &gt; B &gt; C, then _even if_ there existed no way to match exact types (which there is), you have the option of switching over the type of an instance, providing cases that match in the order C, B, A, Base in order to perform a different action for each. This requires no additional knowledge at compile time beyond what you already stipulated for your use case, namely that the entire class hierarchy must be known at compile time.</div></div></div></blockquote><div class=""><br class=""></div></span><div class="">This order requirement is fragile.&nbsp; If you put Base first it will always match, which probably isn’t the intent.&nbsp; I would like to see a solution that requires you to match each type in the hierarchy without being subject to bugs related to ordering of the cases.</div></div></div></blockquote><div class=""><br class=""></div><div class="">Given that the hierarchy is known at compile-time, a solution that would meet your criteria (not being subject to bugs related to ordering) would be diagnostics for unreachable cases (i.e., if Base is matched before A, `case is A` should be flagged as unreachable).</div></div></div></div></div></blockquote><div class=""><br class=""></div></div></div><div class="">That isn’t an adequate solution IMO.&nbsp; First, it forces an ordering of the cases.&nbsp; But more importantly, it will still allow accidentally matching superclass and omitting subclass cases (so long as there are no unreachable cases).</div></div></div></blockquote><div class=""><br class=""></div><div class="">You cannot accidentally match superclasses by incorrect ordering, because it will always result in unreachable cases in a language without multiple inheritance. As to omitting subclasses, what's the harm in that? Suppose you had a hierarchy Base &gt; A &gt; B &gt; C, but Joe the Programmer doesn't know about C. So he switches over the cases exhaustively and uses Base, A, and B exclusively. What problems will he encounter?</div></div></div></div></div></blockquote><div><br class=""></div><div>Maybe in that case he won’t encounter any problems. &nbsp;However, if you have:</div><div><br class=""></div><div>&nbsp;Base</div><div>&nbsp; | &nbsp; &nbsp;|</div><div>C1 C2</div><div>&nbsp;| &nbsp; &nbsp; |</div><div>D1 D2</div><div><br class=""></div><div>And you just switch over Base, C1, and C2 you may have a match for all possible runtime values but you don’t have cases for all of the possible type. &nbsp;Imagine if you have code that is initially written before D1 and D2 are introduced and your intent is to include a case for each possible runtime type. &nbsp;You want the code to fail to compile when D1 and D2 are introduced until you revisit the switch statement, just as it does when you add a new case to an enum. &nbsp;However, given the current tools there is nothing you can do to force this. &nbsp;This is what I meant by “accidentally”. &nbsp;</div><div><br class=""></div><div>Having a tool for preventing these kinds of mistakes seems like a useful thing and puts classes (and protocols if it works with them as well when all conforming types are known) on equal footing with enums in terms of pattern matching. &nbsp;This gives us more options for structuring our code.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">&nbsp;</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=""><div class=""><div class="">I would prefer a solution that requires *all classes* in the hierarchy to be matched exactly.&nbsp; The existing casts would still work for cases when you don’t care about that and *do* want to use a superclass to match subclasses.</div></div></div></blockquote><div class=""><br class=""></div><div class="">I don't understand the use case. This seems esoteric and goes beyond exhaustive pattern matching.</div></div></div></div></div></blockquote><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><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=""><div class=""><span class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><span class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div style="white-space:pre-wrap" class=""><br class=""></div><div style="white-space:pre-wrap" class="">Third, your motivating example in the previous thread already works. Slightly renamed to match the examples above, the following compiles:</div></div></div></blockquote><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div style="white-space:pre-wrap" class=""><br class=""></div><div style="white-space:pre-wrap" class="">```</div><div class=""><span style="white-space:pre-wrap" class="">class Base {
  init() { }
}
class A1 : Base { }
class A2 : Base { }

func foo(_ b: Base) -&gt; Int {
  switch b {
  case is A1: return 1
  case is A2: return 2
  case is Base: return 0
  }
}</span><br class=""></div><div class=""><span style="white-space:pre-wrap" class=""><br class=""></span></div><div class=""><span style="white-space:pre-wrap" class="">let a = A1()
let b = A2()
foo(a) // 1
foo(b) // 2</span><br class=""></div><div class=""><span style="white-space:pre-wrap" class="">```</span></div><div class=""><span style="white-space:pre-wrap" class=""><br class=""></span></div><div class=""><span style="white-space:pre-wrap" class="">There is a warning that `case is Base` is always true. Perhaps something could be done about that diagnostic, since that is after all what you want in a switch statement without a default case.</span></div><div class=""><span style="white-space:pre-wrap" class=""><br class=""></span></div><div class=""><span style="white-space:pre-wrap" class="">I'm sure you were aware of all of these points, so I guess I'm asking, what exactly are you pitching?</span></div></div></div></blockquote><div class=""><br class=""></div></span><div class="">See above.&nbsp; I am looking for a solution that avoids this warning precisely because it will *not* always be true.&nbsp; The compiler gaining special knowledge of the&nbsp;<span style="white-space:pre-wrap" class="">`type(of: instance) == Base.self` pattern could be *part* of a solution but it still doesn’t bind a name the correct type.  For example, with the </span><span style="white-space:pre-wrap" class="">Base &gt; A &gt; B &gt; C hierarchy when I match `type(of: instance) == B.self` I also want a variable bound with a type of `B`.  This gets pretty verbose and requires the compiler to have special knowledge of pretty specific pattern:</span></div><div class=""><br class=""></div><div class=""><span class=""><div class="">func foo(_ b: Base) -&gt; Int {</div><div class="">&nbsp;<span class="">&nbsp;</span>switch b {</div></span><div class="">&nbsp;<span class="">&nbsp;</span>case let base as Base where&nbsp;<span style="white-space:pre-wrap" class="">type(of: instance) == Base.self</span>: return 1</div><div class="">&nbsp;<span class="">&nbsp;</span>case let a as A where&nbsp;<span style="white-space:pre-wrap" class="">type(of: instance) == A.self</span>: return 2</div><div class="">&nbsp;<span class="">&nbsp;</span>case let b as B where&nbsp;<span style="white-space:pre-wrap" class="">type(of: instance) == B.self</span>: return 3</div><div class="">&nbsp;<span class="">&nbsp;</span>case let c as C where&nbsp;<span style="white-space:pre-wrap" class="">type(of: instance) == C.self</span>: return 4</div><div class="">&nbsp;<span class="">&nbsp;</span>}</div><div class="">}</div></div></div></div></blockquote><div class="">&nbsp;<br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class=""></div><div class="">If the compiler could prove exhaustiveness here I would accept that solution.&nbsp; But it seems like an exact match cast operator would be much more elegant. &nbsp;</div><div class=""><br class=""></div><div class="">In any case, anything that requires matching every type in a hierarchy without being subject to case ordering bugs and doesn’t require a default clause would be acceptable to me.&nbsp; That is the problem I would like to see solved.</div></div></div></blockquote><div class=""><br class=""></div><div class="">Looking back, it seems like diagnostics for unreachable cases would meet your criteria exactly and would be the most straightforward. I don't think it would even require an evolution proposal. I would love to see type(of:) work with switch statements out-of-the-box, but that seems more esoteric. None of this requires additional syntax, IMHO.</div></div></div></div></div></blockquote><div class=""><br class=""></div></span><div class="">Diagnostics would be an improvement for sure, but aren’t a complete solution IMO for the reasons noted above.&nbsp; We don’t necessarily need new syntax but I don’t have any great alternatives at the moment.</div><div class=""><div class="h5"><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><span style="white-space:pre-wrap" class=""><br class=""></span></div><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Thu, Aug 25, 2016 at 08:40 Matthew Johnson &lt;<a href="mailto:matthew@anandabits.com" target="_blank" class="">matthew@anandabits.com</a>&gt; wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><blockquote type="cite" class=""><div class="">On Aug 24, 2016, at 9:33 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class=""><div class=""><div dir="ltr" class="">On Wed, Aug 24, 2016 at 9:25 PM, Matthew Johnson via swift-evolution<span class="">&nbsp;</span><span dir="ltr" class="">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-<wbr class="">evolution@swift.org</a>&gt;</span><span class="">&nbsp;</span>wrote:<br class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><br class=""><div class=""><span class=""><blockquote type="cite" class=""><div class="">On Aug 24, 2016, at 9:09 PM, Robert Widmann via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class=""><div class=""><div style="word-wrap:break-word" class=""><div style="word-wrap:break-word" class=""><div class="">I have 3 qualms with this proposal as it stands:</div><div class=""><br class=""></div><div class="">- type(of:) will never lie to you.&nbsp;</div><div class=""><br class=""></div><div class="">The only question it won’t answer to your satisfaction is the dynamic type of the NSString you boxed up as an Any.</div><div class=""><br class=""></div><div class="">- No more keywords without significant justification. &nbsp;</div><div class=""><br class=""></div><div class="">I don’t buy the performance use case at all - if you were properly concerned about performance you would try to use as many of Swift’s static features as possible.</div><div class=""><br class=""></div><div class="">- Especially no more keywords that look like they belong in Rust or PHP!</div><div class=""><br class=""></div><div class="">There is no precedent for the spelling of these operations other than the suffixed punctuation. Given that they’re domain-specific, will definitely be hard to use (given that&nbsp;<span style="font-family:Menlo;font-size:11px;color:rgb(112,61,170)" class="">NSString</span><span style="font-family:Menlo;font-size:11px" class="">(string:&nbsp;</span><span style="font-family:Menlo;font-size:11px;color:rgb(209,47,27)" class="">"Bar”</span><span style="font-family:Menlo;font-size:11px" class="">)<span class="">&nbsp;</span></span><span style="font-size:11px" class="">m<wbr class="">ay not “really” given you an NSString yet that’s what you asked us to check for “<i class="">really</i>"), and will be obviated by the implementation of SE-0083, I can’t see a reason why we need any of this in the language proper.</span></div></div></div></div></blockquote><div class=""><br class=""></div></span><div class="">One related topic to consider is exhaustive pattern matching for classes.&nbsp; Now that&nbsp;SE-0117 has been accepted it will be possible to do this for many classes (I would say most if it weren’t for Objective-C classes being so common in Swift and are imported as `open`).&nbsp; Supporting exhaustive pattern matching well would require some kind of syntax for matching the runtime type exactly.&nbsp; I have imagined this as being “exact match” cast operators, which is what the `really_*` operators are.</div></div></div></blockquote><div class=""><br class=""></div><div class="">I don't understand. As pitched, these operators remove bridging magic, but `Subclass really_is Superclass == true`. How would you use this for classes?</div></div></div></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">Bridging is the use case motivating the pitch.&nbsp; I am bringing up a related use case.</div><div class=""><br class=""></div><div class="">The pitch does not specify&nbsp;`Subclass really_is Superclass == true` and I would argue that this is not the semantics we would want.&nbsp; My interpretation of the proposed solution is:</div><div class=""><br class=""></div><div class="">"I propose the following operators: really_is, really_as, really_as?, and really_as!. These operators would only return a&nbsp;positive result if the type actually was what was being asked for, instead of something that might be able to bridge to that&nbsp;type<span class="">&nbsp;</span><b class="">or a superclass of that type</b>."</div><div class=""><br class=""></div><div class="">We discussed the exhaustive pattern matching previously in this thread:&nbsp;<a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160523/018799.html" target="_blank" class="">https://lists.swift.or<wbr class="">g/pipermail/swift-evolution/We<wbr class="">ek-of-Mon-20160523/018799.html</a><span class=""><wbr class="">&nbsp;</span>where the “exact match” cast operators were called `isExactly` and `asExactly`.</div><div class=""><br class=""></div><div class="">I think the exhaustive pattern matching use case for classes (and protocols if / when we get sealed protocols) is an important one.&nbsp; I also think doing it right requires the ability to match exact types (i.e. not match subclasses).&nbsp; Maybe there is a better mechanism than a new operators but they would certainly do the job well.</div></div></div><div style="word-wrap:break-word" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">&nbsp;</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class="">Do you have an alternative in mind for exhaustive pattern matching if we do not introduce exact match cast operators?</div><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word" class=""><div style="word-wrap:break-word" class=""><div class=""><br class=""></div><div class="">~Robert Widmann</div><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Aug 24, 2016, at 5:08 PM, Charles Srstka via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class=""><div class=""><div style="word-wrap:break-word" class="">MOTIVATION:<div class=""><br class=""></div><div class="">SE-0083 appears to be dead in the water, having been deferred until later in Swift 3 back in May and not having been heard from since then, with the Swift 3 release looming closer and closer. However, the predictability gains that would have been provided by this change remain desirable for cases where one needs to know the actual dynamic type of an entity before any bridging magic is involved. Additionally, performance-critical code may desire the ability to check something’s type quickly without incurring the overhead of Objective-C bridging code.</div><div class=""><br class=""></div><div class="">PROPOSED SOLUTION:</div><div class=""><br class=""></div><div class="">I propose the following operators: really_is, really_as, really_as?, and really_as!. These operators would only return a positive result if the type actually was what was being asked for, instead of something that might be able to bridge to that type.</div><div class=""><br class=""></div><div class="">DETAILED DESIGN:</div><div class=""><br class=""></div><div class=""><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span style="color:rgb(187,44,162)" class="">let</span><span class=""><span class="">&nbsp;</span>foo:<span class="">&nbsp;</span></span><span style="color:rgb(187,44,162)" class="">Any</span><span class=""><span class="">&nbsp;</span>=<span class="">&nbsp;</span></span><span style="color:rgb(209,47,27)" class="">"Foo"</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span style="color:rgb(187,44,162)" class="">let</span><span class=""><span class="">&nbsp;</span>bar:<span class="">&nbsp;</span></span><span style="color:rgb(187,44,162)" class="">Any</span><span class=""><span class="">&nbsp;</span>=<span class="">&nbsp;</span></span><span style="color:rgb(112,61,170)" class="">NSString</span><span class="">(<wbr class="">string:<span class="">&nbsp;</span></span><span style="color:rgb(209,47,27)" class="">"Bar"</span><span class="">)</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class=""><span class=""></span><br class=""></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span style="color:rgb(187,44,162)" class="">let</span><span class=""><span class="">&nbsp;</span>fooIsString =<span class="">&nbsp;</span></span><span style="color:rgb(79,129,135)" class="">foo</span><span class=""><span class="">&nbsp;</span></span><span style="color:rgb(187,44,162)" class="">is</span><span class=""><span class="">&nbsp;</span></span><span style="color:rgb(112,61,170)" class="">String &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// true</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span style="color:rgb(112,61,170)" class=""><span style="color:rgb(187,44,162)" class="">let</span><span class="">&nbsp;fooReallyIsString =&nbsp;</span><span style="color:rgb(79,129,135)" class="">foo</span><span class="">&nbsp;</span><span style="color:rgb(187,44,162)" class="">really_is</span><span class="">&nbsp;</span><span class="">String &nbsp; &nbsp; // true</span></span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span style="color:rgb(112,61,170)" class=""><br class=""></span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span style="color:rgb(187,44,162)" class="">let</span><span class=""><span class="">&nbsp;</span>fooIsNSString =<span class="">&nbsp;</span></span><span style="color:rgb(79,129,135)" class="">foo</span><span class=""><span class="">&nbsp;</span></span><span style="color:rgb(187,44,162)" class="">is</span><span class=""><span class="">&nbsp;</span></span><span style="color:rgb(112,61,170)" class="">NSString &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// true</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span style="color:rgb(112,61,170)" class=""><span style="color:rgb(187,44,162)" class="">let</span><span class="">&nbsp;fooReallyIsNSString =&nbsp;</span><span style="color:rgb(79,129,135)" class="">foo</span><span class="">&nbsp;</span><span style="color:rgb(187,44,162)" class="">really_is</span><span class="">&nbsp;</span><span class="">NSString // false</span></span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class=""><span class=""></span><br class=""></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span style="color:rgb(187,44,162)" class="">let</span><span class=""><span class="">&nbsp;</span>barIsString =<span class="">&nbsp;</span></span><span style="color:rgb(79,129,135)" class="">bar</span><span class=""><span class="">&nbsp;</span></span><span style="color:rgb(187,44,162)" class="">is</span><span class=""><span class="">&nbsp;</span></span><span style="color:rgb(112,61,170)" class="">String &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// true</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span style="color:rgb(112,61,170)" class=""><span style="color:rgb(187,44,162)" class="">let</span><span class="">&nbsp;barReallyIsString =&nbsp;</span><span style="color:rgb(79,129,135)" class="">bar</span><span class="">&nbsp;</span><span style="color:rgb(187,44,162)" class="">really_is</span><span class="">&nbsp;</span><span class="">String &nbsp; &nbsp; // false</span></span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span style="color:rgb(112,61,170)" class=""><br class=""></span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span style="color:rgb(187,44,162)" class="">let</span><span class=""><span class="">&nbsp;</span>barIsNSString =<span class="">&nbsp;</span></span><span style="color:rgb(79,129,135)" class="">bar</span><span class=""><span class="">&nbsp;</span></span><span style="color:rgb(187,44,162)" class="">is</span><span class=""><span class="">&nbsp;</span></span><span style="color:rgb(112,61,170)" class="">NSString &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// true</span></div></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span style="color:rgb(112,61,170)" class=""><span style="color:rgb(187,44,162)" class="">let</span><span class="">&nbsp;barReallyIsNSString =&nbsp;</span><span style="color:rgb(79,129,135)" class="">bar</span><span class="">&nbsp;</span></span><span style="color:rgb(187,44,162)" class="">really_is</span><span class="">&nbsp;</span><span style="color:rgb(112,61,170)" class="">NSString // true</span></div><div class=""><span style="color:rgb(112,61,170)" class=""><br class=""></span></div><div class=""><span style="color:rgb(112,61,170)" class=""><span class="">ALTERNATIVES CONSIDERED:</span></span></div><div class=""><span style="color:rgb(112,61,170)" class=""><span class=""><br class=""></span></span></div><div class=""><span class="">Stick with using an unholy combination of Mirror and unsafeBitCast when you need to know what you’ve actually got.</span></div><div class=""><span class=""><br class=""></span></div><div class=""><span class="">Charles</span></div><div class=""><span class=""><br class=""></span></div></div>______________________________<wbr class="">_________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/mailma<wbr class="">n/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class=""></div></div>______________________________<wbr class="">_________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/mailma<wbr class="">n/listinfo/swift-evolution</a><br class=""></div></blockquote></div></div></div><br class=""></div><br class="">______________________________<wbr class="">_________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailma<wbr class="">n/listinfo/swift-evolution</a></blockquote></div></div></div></div></blockquote></div></div></blockquote></div></div></div></blockquote></div></div></div></div></blockquote></div></div></div></div></blockquote></div></div></div><br class=""></div></blockquote></div><br class=""></div></div>
</div></blockquote></div><br class=""></body></html>