<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 May 25, 2016, at 1:09 PM, 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" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="gmail_extra"><div class="gmail_quote">On Wed, May 25, 2016 at 12:49 PM, Matthew Johnson via swift-evolution<span class="Apple-converted-space">&nbsp;</span><span dir="ltr" class="">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt;</span>wrote:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div dir="auto" class=""><div class=""><br class=""><br class="">Sent from my iPad</div><span class=""><div class=""><br class="">On May 25, 2016, at 12:41 PM, Charlie Monroe &lt;<a href="mailto:charlie@charliemonroe.net" target="_blank" class="">charlie@charliemonroe.net</a>&gt; wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div class=""><blockquote type="cite" class=""><div dir="auto" class=""><div class="">Got it.&nbsp; You could also say it is safer because you can't have a supertype case "swallow" a subtype value accidentally.&nbsp; An "exact type" cast would prevent this possibility.</div></div></blockquote><div class=""><br class=""></div><div class="">This still can be an issue since you still need to do the switch in init(instance:), but it's just one place within the entire module, so it can be more easily managed...</div></div></div></blockquote><div class=""><br class=""></div></span>Yes, agree.&nbsp; That's why your enum is safer.&nbsp; I think we do need an exact type cast to prevent this problem. &nbsp;'isExaclty' and 'asExactly' seem are a bit verbose but are very clear.&nbsp; I can't think of anything I like that is more concise.<div class=""><div class="h5"><div class=""><br class=""></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">This doesn't at all solve the parent issue of switching exhaustively, but switching over dynamicType distinguishes subclasses from base classes quite adequately:</div><div class=""><br class=""></div><div class="">```</div><div class="">class Foo { }</div><div class=""><br class=""></div><div class="">class Bar : Foo { }</div><div class=""><br class=""></div><div class="">class Baz : Foo { }</div><div class=""><br class=""></div><div class="">let b = Bar()</div><div class=""><br class=""></div><div class="">switch b.dynamicType {</div><div class="">case let t where t == Foo.self:</div><div class="">&nbsp; &nbsp; print("Foo!")</div><div class="">case let t where t == Bar.self:</div><div class="">&nbsp; &nbsp; print("Bar!")</div><div class="">case let t where t == Baz.self:</div><div class="">&nbsp; &nbsp; print("Baz!")</div><div class="">default:</div><div class="">&nbsp; &nbsp; print("Boo...")</div><div class="">}</div><div class="">```</div></div></div></div></div></blockquote><div><br class=""></div><div>It’s good to know about this capability, but it &nbsp;isn’t really a solution. &nbsp;It doesn’t give you a name bound to `b` with the appropriate type for the case. &nbsp;`t` is bound to `Bar.self`.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div><div class="">&nbsp;</div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div dir="auto" class=""><div class=""><div class="h5"><div class=""><div class=""><blockquote type="cite" class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div dir="auto" class=""><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class=""><div class=""><div class=""><br class=""></div><div class="">enum AnimalSubclasses {</div><div class=""><span style="white-space: pre-wrap;" class="">        </span></div><div class=""><span style="white-space: pre-wrap;" class="">        </span>case Dog</div><div class=""><span style="white-space: pre-wrap;" class="">        </span>case Cat</div><div class=""><br class=""></div><div class=""><span style="white-space: pre-wrap;" class="">        </span>init(instance: Animal) {</div><div class=""><span style="white-space: pre-wrap;" class="">                </span>switch instance {</div><div class=""><span style="white-space: pre-wrap;" class="">                </span>case is Dog: self = .Dog</div><div class=""><span style="white-space: pre-wrap;" class="">                </span>case is Cat: self = .Cat</div><div class=""><span style="white-space: pre-wrap;" class="">                </span>default: fatalError("Unhandled instance \(instance)!")</div><div class=""><span style="white-space: pre-wrap;" class="">        </span>}</div><div class=""><br class=""></div><div class="">}</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 10px; 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="">One thing I have considered that might also be worth introducing is an exact match cast.&nbsp; This would prevent the possibility of putting a superclass case first and having it “steal” subclasses which were intended to be covered by a case later in the switch.&nbsp; If we introduce exact match you would be able to write a switch that must always cover every concrete type, including all subclasses. &nbsp;</div><br style="font-family: Helvetica; font-size: 10px; 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=""><blockquote type="cite" style="font-family: Helvetica; font-size: 10px; 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=""><div style="word-wrap: break-word;" class=""><div class=""><br class=""></div><div class="">Charlie</div><div class=""><br class=""></div><br class=""><div class=""><blockquote type="cite" class=""><div class="">On May 25, 2016, at 4:41 AM, Leonardo Pessoa 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 dir="auto" class=""><div class=""><div style="font-family: Calibri, sans-serif; font-size: 11pt;" class="">Limiting the amount of subclasses is not really a good idea as you would need to introduce another mechanism in the language while the proposed feature requires much less. And you're thinking only about the restrictive set (internal and private) and forgetting the more open end (public). Why is it so bad for this proposal to support requiring the default case? If its possible for the compiler to discover you covered all possible cases it would be fine not having default but IMHO in most cases it will find out there are more not explicitly covered.<br class=""></div></div><div dir="ltr" class=""><hr class=""><span style="font-family: Calibri, sans-serif; font-size: 11pt; font-weight: bold;" class="">From:<span class="">&nbsp;</span></span><span style="font-family: Calibri, sans-serif; font-size: 11pt;" class=""><a href="mailto:davesweeris@mac.com" target="_blank" class="">David Sweeris</a></span><br class=""><span style="font-family: Calibri, sans-serif; font-size: 11pt; font-weight: bold;" class="">Sent:<span class="">&nbsp;</span></span><span style="font-family: Calibri, sans-serif; font-size: 11pt;" class="">‎24/‎05/‎2016 11:01 PM</span><br class=""><span style="font-family: Calibri, sans-serif; font-size: 11pt; font-weight: bold;" class="">To:<span class="">&nbsp;</span></span><span style="font-family: Calibri, sans-serif; font-size: 11pt;" class=""><a href="mailto:austinzheng@gmail.com" target="_blank" class="">Austin Zheng</a></span><br class=""><span style="font-family: Calibri, sans-serif; font-size: 11pt; font-weight: bold;" class="">Cc:<span class="">&nbsp;</span></span><span style="font-family: Calibri, sans-serif; font-size: 11pt;" class=""><a href="mailto:me@lmpessoa.com" target="_blank" class="">Leonardo Pessoa</a>;<span class="">&nbsp;</span><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution</a></span><br class=""><span style="font-family: Calibri, sans-serif; font-size: 11pt; font-weight: bold;" class="">Subject:<span class="">&nbsp;</span></span><span style="font-family: Calibri, sans-serif; font-size: 11pt;" class="">Re: [swift-evolution] [Pitch] Exhaustive pattern matching forprotocols and classes</span><br class=""><br class=""></div><div class="">Or if there was a way to declare that a class/protocol can only have a defined set of subclasses/conforming types.<br class=""><br class="">Sent from my iPhone</div><div class=""><br class="">On May 24, 2016, at 15:35, Austin Zheng via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class="">If you pattern match on a type that is declared internal or private, it is impossible for the compiler to not have an exhaustive list of subclasses that it can check against.<div class=""><br class=""></div><div class="">Austin</div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Tue, May 24, 2016 at 1:29 PM, Leonardo Pessoa<span class="">&nbsp;</span><span dir="ltr" class="">&lt;<a href="mailto:me@lmpessoa.com" target="_blank" class="">me@lmpessoa.com</a>&gt;</span><span class="">&nbsp;</span>wrote:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;">I like this but I think it would be a lot hard to ensure you have all<br class="">subclasses covered. Think of frameworks that could provide many<br class="">unsealed classes. You could also have an object that would have to<br class="">handle a large subtree (NSObject?) and the order in which the cases<br class="">are evaluated would matter just as in exception handling in languages<br class="">such as Java (or require some evaluation from the compiler to raise<br class="">warnings). I'm +1 for this but these should be open-ended like strings<br class="">and require the default case.<br class=""><br class="">On 24 May 2016 at 17:08, Austin Zheng via swift-evolution<br class=""><div class=""><div class="">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:<br class="">&gt; I have been hoping for the exhaustive pattern matching feature for a while<br class="">&gt; now, and would love to see a proposal.<br class="">&gt;<br class="">&gt; Austin<br class="">&gt;<br class="">&gt; On Tue, May 24, 2016 at 1:01 PM, Matthew Johnson via swift-evolution<br class="">&gt; &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:<br class="">&gt;&gt;<br class="">&gt;&gt; Swift currently requires a default pattern matching clause when you switch<br class="">&gt;&gt; on an existential or a non-final class even if the protocol or class is<br class="">&gt;&gt; non-public and all cases are covered.&nbsp; It would be really nice if the<br class="">&gt;&gt; default clause were not necessary in this case.&nbsp; The compiler has the<br class="">&gt;&gt; necessary information to prove exhaustiveness.<br class="">&gt;&gt;<br class="">&gt;&gt; Related to this is the idea of introducing something like a `sealed`<br class="">&gt;&gt; modifier that could be applied to public protocols and classes.&nbsp; The<br class="">&gt;&gt; protocol or class would be visible when the module is imported, but<br class="">&gt;&gt; conformances or subclasses outside the declaring module would be prohibited.<br class="">&gt;&gt; Internal and private protocols and classes would implicitly be sealed since<br class="">&gt;&gt; they are not visible outside the module.&nbsp; Any protocols that inherit from a<br class="">&gt;&gt; sealed protocol or classes that inherit from a sealed class would also be<br class="">&gt;&gt; implicitly sealed (if we didn’t do this the sealing of the superprotocol /<br class="">&gt;&gt; superclass could be violated by conforming to or inheriting from a<br class="">&gt;&gt; subprotocol / subclass).<br class="">&gt;&gt;<br class="">&gt;&gt; Here are examples that I would like to see be valid:<br class="">&gt;&gt;<br class="">&gt;&gt; protocol P {}<br class="">&gt;&gt; // alternatively public sealed protocol P {}<br class="">&gt;&gt; struct P1: P {}<br class="">&gt;&gt; struct P2: P {}<br class="">&gt;&gt;<br class="">&gt;&gt; func p(p: P) -&gt; Int {<br class="">&gt;&gt;&nbsp; &nbsp; &nbsp;switch p {<br class="">&gt;&gt;&nbsp; &nbsp; &nbsp;case is P1: return 1 // alternatively an `as` cast<br class="">&gt;&gt;&nbsp; &nbsp; &nbsp;case is P2: return 2 // alternatively an `as` cast<br class="">&gt;&gt;&nbsp; &nbsp; &nbsp;}<br class="">&gt;&gt; }<br class="">&gt;&gt;<br class="">&gt;&gt; class C {}<br class="">&gt;&gt; // alternatively public sealed class C {}<br class="">&gt;&gt; class C1: C {}<br class="">&gt;&gt; class C2: C {}<br class="">&gt;&gt;<br class="">&gt;&gt; func c(c: C) -&gt; Int {<br class="">&gt;&gt;&nbsp; &nbsp; &nbsp;switch c {<br class="">&gt;&gt;&nbsp; &nbsp; &nbsp;case is C1: return 1 // alternatively an `as` cast<br class="">&gt;&gt;&nbsp; &nbsp; &nbsp;case is C2: return 2 // alternatively an `as` cast<br class="">&gt;&gt;&nbsp; &nbsp; &nbsp;case is C: return 0&nbsp; &nbsp;// alternatively an `as` cast<br class="">&gt;&gt;&nbsp; &nbsp; &nbsp;}<br class="">&gt;&gt; }<br class="">&gt;&gt;<br class="">&gt;&gt; I am wondering if this is something the community is interested in.&nbsp; If<br class="">&gt;&gt; so, I am wondering if this is something that might be possible in the Swift<br class="">&gt;&gt; 3 timeframe (maybe just for private and internal protocols and classes) or<br class="">&gt;&gt; if it should wait for Swift 4 (this is likely the case).<br class="">&gt;&gt;<br class="">&gt;&gt; -Matthew<br class="">&gt;&gt; _______________________________________________<br class="">&gt;&gt; swift-evolution mailing list<br class="">&gt;&gt;<span class="">&nbsp;</span><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class="">&gt;&gt;<span class="">&nbsp;</span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">&gt;<br class="">&gt;<br class="">&gt;<br class="">&gt; _______________________________________________<br class="">&gt; swift-evolution mailing list<br class="">&gt;<span class="">&nbsp;</span><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class="">&gt;<span class="">&nbsp;</span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">&gt;<br class=""></div></div></blockquote></div><br class=""></div></div></blockquote><blockquote type="cite" class=""><div class=""><span class="">_______________________________________________</span><br class=""><span class="">swift-evolution mailing list</span><br class=""><span class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a></span><br class=""><span class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br class=""></div></blockquote></div>_______________________________________________<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/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class=""></div>_______________________________________________<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/mailman/listinfo/swift-evolution</a></div></blockquote></div></blockquote></div><br class=""></div></blockquote></div></div></blockquote></div><br class=""></div></blockquote></div></div></div></div></div><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" 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/mailman/listinfo/swift-evolution</a></blockquote></div></div></div></div></blockquote></div><br class=""></body></html>