<div dir="ltr"><div style="white-space:pre-wrap">Charles clarified that indeed he was pitching casting operators that match subclasses.<br><br>If the compiler knows that a class is sealed, why do you think there&#39;s a new keyword needed for the compiler to prove exhaustiveness?</div><div style="white-space:pre-wrap"><br></div><div style="white-space:pre-wrap">First, you can already match exact types by writing `type(of: instance) == Base.self` (which doesn&#39;t evaluate to true if instance is of a subclass of Base).</div><div style="white-space:pre-wrap"><br></div><div style="white-space:pre-wrap">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 style="white-space:pre-wrap"><br></div><div style="white-space:pre-wrap">Third, your motivating example in the previous thread already works. Slightly renamed to match the examples above, the following compiles:</div><div style="white-space:pre-wrap"><br></div><div style="white-space:pre-wrap">```</div><div><span style="white-space:pre-wrap">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></div><div><span style="white-space:pre-wrap"><br></span></div><div><span style="white-space:pre-wrap">let a = A1()
let b = A2()
foo(a) // 1
foo(b) // 2</span><br></div><div><span style="white-space:pre-wrap">```</span></div><div><span style="white-space:pre-wrap"><br></span></div><div><span style="white-space:pre-wrap">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><span style="white-space:pre-wrap"><br></span></div><div><span style="white-space:pre-wrap">I&#39;m sure you were aware of all of these points, so I guess I&#39;m asking, what exactly are you pitching?</span></div><div><span style="white-space:pre-wrap"><br></span></div><br><div class="gmail_quote"><div dir="ltr">On Thu, Aug 25, 2016 at 08:40 Matthew Johnson &lt;<a href="mailto:matthew@anandabits.com" target="_blank">matthew@anandabits.com</a>&gt; wrote:<br></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"><div><blockquote type="cite"><div>On Aug 24, 2016, at 9:33 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br><div><div dir="ltr">On Wed, Aug 24, 2016 at 9:25 PM, Matthew Johnson via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><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"><br><div><span><blockquote type="cite"><div>On Aug 24, 2016, at 9:09 PM, Robert Widmann via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br><div><div style="word-wrap:break-word"><div style="word-wrap:break-word"><div>I have 3 qualms with this proposal as it stands:</div><div><br></div><div>- type(of:) will never lie to you. </div><div><br></div><div>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><br></div><div>- No more keywords without significant justification.  </div><div><br></div><div>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><br></div><div>- Especially no more keywords that look like they belong in Rust or PHP!</div><div><br></div><div>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 <span style="font-family:Menlo;font-size:11px;color:rgb(112,61,170)">NSString</span><span style="font-family:Menlo;font-size:11px">(string: </span><span style="font-family:Menlo;font-size:11px;color:rgb(209,47,27)">&quot;Bar”</span><span style="font-family:Menlo;font-size:11px">) </span><span style="font-size:11px">may not “really” given you an NSString yet that’s what you asked us to check for “<i>really</i>&quot;), 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><br></div></span><div>One related topic to consider is exhaustive pattern matching for classes.  Now that 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`).  Supporting exhaustive pattern matching well would require some kind of syntax for matching the runtime type exactly.  I have imagined this as being “exact match” cast operators, which is what the `really_*` operators are.</div></div></div></blockquote><div><br></div><div>I don&#39;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><br></div></div></div><div style="word-wrap:break-word"><div><div>Bridging is the use case motivating the pitch.  I am bringing up a related use case.</div><div><br></div><div>The pitch does not specify `Subclass really_is Superclass == true` and I would argue that this is not the semantics we would want.  My interpretation of the proposed solution is:</div><div><br></div><div>&quot;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 <b>or a superclass of that type</b>.&quot;</div><div><br></div><div>We discussed the exhaustive pattern matching previously in this thread: <a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160523/018799.html" target="_blank">https://lists.swift.<wbr>org/pipermail/swift-evolution/<wbr>Week-of-Mon-20160523/018799.<wbr>html</a> where the “exact match” cast operators were called `isExactly` and `asExactly`.</div><div><br></div><div>I think the exhaustive pattern matching use case for classes (and protocols if / when we get sealed protocols) is an important one.  I also think doing it right requires the ability to match exact types (i.e. not match subclasses).  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"><div><br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> </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"><div><div>Do you have an alternative in mind for exhaustive pattern matching if we do not introduce exact match cast operators?</div><div><div><br><blockquote type="cite"><div><div style="word-wrap:break-word"><div style="word-wrap:break-word"><div><br></div><div>~Robert Widmann</div><br><div><blockquote type="cite"><div>On Aug 24, 2016, at 5:08 PM, Charles Srstka via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br><div><div style="word-wrap:break-word">MOTIVATION:<div><br></div><div>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><br></div><div>PROPOSED SOLUTION:</div><div><br></div><div>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><br></div><div>DETAILED DESIGN:</div><div><br></div><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:#bb2ca2">let</span><span> foo: </span><span style="color:#bb2ca2">Any</span><span> = </span><span style="color:#d12f1b">&quot;Foo&quot;</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:#bb2ca2">let</span><span> bar: </span><span style="color:#bb2ca2">Any</span><span> = </span><span style="color:#703daa">NSString</span><span>(string: </span><span style="color:#d12f1b">&quot;Bar&quot;</span><span>)</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><span></span><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:#bb2ca2">let</span><span> fooIsString = </span><span style="color:#4f8187">foo</span><span> </span><span style="color:#bb2ca2">is</span><span> </span><span style="color:#703daa">String                  // true</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:#703daa"><span style="color:rgb(187,44,162)">let</span><span> fooReallyIsString = </span><span style="color:rgb(79,129,135)">foo</span><span> </span><span style="color:rgb(187,44,162)">really_is</span><span> </span><span>String     // true</span></span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:#703daa"><br></span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:#bb2ca2">let</span><span> fooIsNSString = </span><span style="color:#4f8187">foo</span><span> </span><span style="color:#bb2ca2">is</span><span> </span><span style="color:#703daa">NSString              // true</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:#703daa"><span style="color:rgb(187,44,162)">let</span><span> fooReallyIsNSString = </span><span style="color:rgb(79,129,135)">foo</span><span> </span><span style="color:rgb(187,44,162)">really_is</span><span> </span><span>NSString // false</span></span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><span></span><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:#bb2ca2">let</span><span> barIsString = </span><span style="color:#4f8187">bar</span><span> </span><span style="color:#bb2ca2">is</span><span> </span><span style="color:#703daa">String                  // true</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:#703daa"><span style="color:rgb(187,44,162)">let</span><span> barReallyIsString = </span><span style="color:rgb(79,129,135)">bar</span><span> </span><span style="color:rgb(187,44,162)">really_is</span><span> </span><span>String     // false</span></span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:#703daa"><br></span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:#bb2ca2">let</span><span> barIsNSString = </span><span style="color:#4f8187">bar</span><span> </span><span style="color:#bb2ca2">is</span><span> </span><span style="color:#703daa">NSString              // true</span></div></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:#703daa"><span style="color:rgb(187,44,162)">let</span><span> barReallyIsNSString = </span><span style="color:rgb(79,129,135)">bar</span><span> </span></span><span style="color:rgb(187,44,162)">really_is</span><span> </span><span style="color:rgb(112,61,170)">NSString // true</span></div><div><span style="color:#703daa"><br></span></div><div><span style="color:#703daa"><span>ALTERNATIVES CONSIDERED:</span></span></div><div><span style="color:#703daa"><span><br></span></span></div><div><span>Stick with using an unholy combination of Mirror and unsafeBitCast when you need to know what you’ve actually got.</span></div><div><span><br></span></div><div><span>Charles</span></div><div><span><br></span></div></div>______________________________<wbr>_________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br></div></blockquote></div><br></div></div>______________________________<wbr>_________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br></div></blockquote></div></div></div><br></div><br>______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
<br></blockquote></div><br></div></div>
</div></blockquote></div></div></blockquote></div></div>