<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 Jan 3, 2018, at 11:07 AM, Dave DeLong via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">IMO this is still too large of a hammer for this problem.<div class=""><br class=""></div><div class="">This whole “unexpected case” thing is only a problem when you’re linking libraries that are external to/shipped independently of&nbsp;your app. Right now, the *only* case where this might exist is Swift on the server. We *might* run in to this in the future once the ABI stabilizes and we have the Swift libraries shipping as part of iOS/macOS/Linux. Other than this, unexpected enum cases won’t really be a problem developers have to deal with.</div><div class=""><br class=""></div><div class="">Because this will be such a relatively rare problem, I feel like a syntax change like what’s being proposed is a too-massive hammer for such a small nail.</div><div class=""><br class=""></div><div class="">What feels far more appropriate is:</div><div class=""><br class=""></div><div class="">🅰️ Teaching the compiler/checker/whatever about the linking semantics of modules. For modules that are packaged inside the final built product, there is no need to deal with any unexpected cases, because we already have the exhaustiveness check appropriate for that scenario (regardless of whether the module is shipped as a binary or compiled from source). The app author decides when to update their dependencies, and updating those dependencies will produce new warnings/errors as the compiler notices new or deprecated cases. This is the current state of things and is completely orthogonal to the entire discussion.</div></div></div></blockquote><div><br class=""></div><div>John McCall sketched out a vision of what a solution to this might look like here:&nbsp;<a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171218/042333.html" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171218/042333.html</a>.&nbsp;</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><br class=""></div><div class="">and</div><div class=""><br class=""></div><div class="">🅱️ Adding an attribute (@frozen, @tangled, @moana, @whatever) that can be used to decorate an enum declaration. This attribute would only need to be consulted on enums where the compiler can determine that the module will *not* be part of the final built product. (Ie, it’s an “external” module, in my nomenclature). This, then, is a module that can update independently of the final app, and therefore there are two possible cases:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>1️⃣ If the enum is decorated with @frozen, then I, as an app author, have the assurance that the enum case will not change in future releases of the library, and I can safely switch on all known cases and not have to provide a default case.&nbsp;</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>2️⃣ If the enum is NOT decorated with @frozen, then I, as an app author, have to account for the possibility that the module may update from underneath my app, and I have to handle an unknown case. This is simple: the compiler should require me to add a “default:” case to my switch statement. This warning is produced IFF: the enum is coming from an external module, and the enum is not decorated with @frozen.</div></div></div></blockquote><div><br class=""></div><div>This does not help people who need to write a switch statement over an enum vended by a module that ships with the OS keep their code up to date as the module adds new cases. I find the example of `SKPaymentTransactionState` provided by Brent Royal-Gordon here:&nbsp;<a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170904/039512.html" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170904/039512.html</a>&nbsp;to be compelling. &nbsp;There are rare but legitimate reasons to switch over all known cases of a non-@frozen enum that ship with the OS. &nbsp;These use cases deserve proper language support. &nbsp;I think Jordan’s solution strikes a good balance.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><br class=""></div><div class=""><br class=""></div><div class="">==========</div><div class=""><br class=""></div><div class="">With this proposal, we only have one thing to consider: the spelling of @frozen/@moana/@whatever that we decorate enums in external modules with. Other than that, the existing behavior we currently have is completely capable of covering the possibilities: we just keep using a “default:” case whenever the compiler can’t guarantee that we can be exhaustive in our switching.</div><div class=""><br class=""></div><div class="">Where the real work would be is teaching the compiler about internally-vs-externally linked modules.</div><div class=""><br class=""></div><div class="">Dave<br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Jan 2, 2018, at 7:07 PM, Jordan Rose via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">[Proposal:&nbsp;<a href="https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md" class="" style="font-family: Helvetica, arial, sans-serif;">https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md</a>]</div><div class=""><br class=""></div><div class="">Whew! Thanks for your feedback, everyone. On the lighter side of feedback—naming things—it seems that most people seem to like '<b class="">@frozen</b>', and that does in fact have the connotations we want it to have. I like it too.</div><div class=""><br class=""></div><div class="">More seriously, this discussion has convinced me that it's worth including what the proposal discusses as a <b class="">'future' case</b>. The key point that swayed me is that this can produce a <i class="">warning</i>&nbsp;when the switch is missing a case rather than an <i class="">error,</i>&nbsp;which both provides the necessary compiler feedback to update your code and allows your dependencies to continue compiling when you update to a newer SDK. I know people on both&nbsp;sides won't be 100% satisfied with this, but does it seem like a reasonable compromise?</div><div class=""><br class=""></div><div class="">The next question is how to spell it. I'm leaning towards `unexpected case:`, which (a) is backwards-compatible, and (b) also handles "private cases", either the fake kind that you can do in C (as described in the proposal), or some real feature we might add to Swift some day. `unknown case:` isn't bad either.</div><div class=""><br class=""></div><div class="">I too would like to just do `unknown:` or `unexpected:` but that's technically a source-breaking change:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">switch foo {</div><div class="">case bar:</div><div class="">&nbsp; unknown:</div><div class="">&nbsp; while baz() {</div><div class="">&nbsp; &nbsp; while garply() {</div><div class="">&nbsp; &nbsp; &nbsp; if quux() {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; break unknown</div><div class="">&nbsp; &nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; }</div><div class="">}</div></blockquote><div class=""><br class=""></div><div class="">Another downside of the `unexpected case:` spelling is that it doesn't work as part of a larger pattern. I don't have a good answer for that one, but perhaps it's acceptable for now.</div><div class=""><br class=""></div><div class="">I'll write up a revision of the proposal soon and make sure the core team gets my recommendation when they discuss the results of the review.</div><div class=""><br class=""></div><div class="">---</div><div class=""><br class=""></div><div class=""><div class="">I'll respond to a few of the more intricate discussions tomorrow, including the syntax of putting a new declaration inside the enum rather than outside. Thank you again, everyone, and happy new year!</div></div><div class=""><br class=""></div><div class="">Jordan</div><div class=""><br class=""></div></div>_______________________________________________<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" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class=""></div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>