<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">The mega-thread about SE-0192 is a bit large, and I’d like to talk about one specific point. &nbsp;In the review conversation, there has been significant objection to the idea of requiring a ‘default’ for switches over enums that are non-exhaustive. &nbsp;<div class=""><br class=""></div><div class=""><div class="">This whole discussion is happening because the ABI stability work is introducing a new concept to enums - invisible members/inhabitants (and making them reasonably prominent). &nbsp;A closely related feature is that may come up in the future is "private cases”. &nbsp;Private cases are orthogonal to API evolution and may even occur on one that is defined to be exhaustive.</div><div class=""><br class=""></div><div class="">Private cases and non-exhaustive enums affect the enum in the same way: they say that the enum can have values that a client does not know about. &nbsp;Swift requires switches to process *all* of the dynamically possible values, which is why the original proposal started out with the simplest possible solution: just require ‘default' when processing the cases.</div></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><b class="">The problems with&nbsp;“unknown case:”</b></div><div class=""><br class=""></div><div class="">The popular solution to this probably is currently being pitched as a change to the proposal (<a href="https://github.com/apple/swift-evolution/pull/777" class="">https://github.com/apple/swift-evolution/pull/777</a>) which introduces a new concept “unknown case” as a near-alias for ‘default’:</div><div class=""><a href="https://github.com/jrose-apple/swift-evolution/blob/60d8698d7cde2e1824789b952558bade541415f1/proposals/0192-non-exhaustive-enums.md#unknown-case" class="">https://github.com/jrose-apple/swift-evolution/blob/60d8698d7cde2e1824789b952558bade541415f1/proposals/0192-non-exhaustive-enums.md#unknown-case</a><br class=""><div class=""><br class=""></div><div class="">In short, I think this is the wrong way to solve the problem. &nbsp;I have several concerns with this:</div><div class=""><br class=""></div><div class="">1) Unlike in C, switch is Swift is a general pattern matching facility - not a way of processing integers. &nbsp;It supports recursive patterns and values, and enums are not necessarily at the top-level of the pattern. &nbsp; https://github.com/apple/swift/blob/master/docs/PatternMatching.rst is a document from early evolution of Swift but contains a good general introduction to this.</div><div class=""><br class=""></div><div class="">2) Swift also has other facilities for pattern matching, including ‘if case’. &nbsp;Making switch inconsistent with them is not great.</div><div class=""><br class=""></div><div class="">3) As pitched, “unknown case” will match *known* cases too, which is (in my opinion :-) oxymoronic.</div><div class=""><br class=""></div><div class=""><div class="">4) “unknown case:” changes the basic swift grammar (it isn’t just a modifier on case) because case *requires* a pattern. &nbsp;A better spelling would be “unknown default:” which is closer to the semantic provided anyway.</div><div class=""><br class=""></div></div><div class="">5) It is entirely reasonable (though rare in practice) to want to handle default and unknown cases in the same switch.</div><div class=""><div class=""><br class=""></div></div><div class=""><br class=""></div><div class="">For all the above reasons, ‘unknown case:' becomes a weird wart put on the side of switch/case, not something that fits in naturally with the rest of Swift.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><b class="">Alternative proposal:</b></div><div class=""><br class=""></div><div class="">Instead of introducing a new modifier on case/switch, lets just introduce a new pattern matching operator that *matches unknown cases*, called “#unknown” or “.#unknown” or something (I’m not wed to the syntax, better suggestions welcome :).</div><div class=""><br class=""></div><div class="">In the simple case most people are talking about, instead of writing “unknown case:” you’d write “case #unknown:” which isn’t much different. &nbsp;The nice thing about this is that #unknown slots directly into our pattern matching system. &nbsp;Here is a weird example:</div><div class=""><br class=""></div><div class="">switch someIntEnumTuple {</div><div class="">case (1, .X): &nbsp; … matches one combination of int and tuple...</div><div class="">case (2, .Y): &nbsp; … matches another combination of int and tuple...</div><div class="">case (_, #unknown): … &nbsp;matches any int and any unknown enum case ...</div><div class="">case default: &nbsp;… matches anything ...</div><div class="">}</div><div class=""><br class=""></div><div class="">Furthermore, if you have a switch that enumerates all of the known cases and use #unknown, then it falls out of the model that new cases (e.g. due to an SDK upgrade or an updated source package) produces the existing build error. &nbsp;As with the original proposal, you can always choose to use “default:” instead of “case #unknown:” if you don’t like that behavior.</div><div class=""><br class=""></div><div class="">Of course, if you have an exhaustive enum (e.g. one defined in your own module or explicitly marked as such) then #unknown matches nothing, so we should warn about it being pointless.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">This addresses my concerns above:</div><div class=""><br class=""></div><div class="">1) This fits into patterns in recursive positions, and slots directly into the existing grammar for patterns. &nbsp;It would be a very simple extension to the compiler instead of a special case added to switch/case.</div><div class=""><br class=""></div><div class="">2) Because it slots into the pattern grammar, it works directly with 'if case’ and the other pattern matching stuff.</div><div class=""><br class=""></div><div class="">3) Doesn’t match known cases.</div><div class=""><br class=""></div><div class="">4) Doesn’t change the case grammar, it just adds a new pattern terminal production.</div><div class=""><br class=""></div><div class="">5) Allows weird cases like the example above.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">All that said, the #unknown spelling isn’t great, but I’m sure we can find something else nice.</div><div class=""><br class=""></div><div class="">Thoughts?</div><div class=""><br class=""></div><div class="">-Chris</div><div class=""><br class=""></div><div class=""><br class=""></div></div></body></html>