[swift-evolution] [swift-evolution-announce] [Review] SE 0192 - Non-Exhaustive Enums

Kevin Ballard kevin at sb.org
Tue Dec 19 17:31:01 CST 2017

> On Dec 19, 2017, at 2:58 PM, Ted Kremenek <kremenek at apple.com> wrote:
> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md <https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md>
> What is your evaluation of the proposal?

Overall I like it, but I have some issues.

I’m not completely sold yet on the idea that public enums should be non-exhaustive by default, as I believe every single public enum I’ve ever written definitely wants to be exhaustive. I’m tempted to say that enums exposed by frameworks that need to maintain future-compatibility (such as Apple’s frameworks) want non-exhaustive by default, but enums exposed by third-party frameworks that follow semantic versioning are likely to want exhaustive by default.

In fact, this brings to mind another difference between enums in Apple frameworks and enums in third-party Swift frameworks, which is the former is exclusively C-compatible enums whereas the latter is going to have a lot of enums that carry associated values. I have no data to support this but I’m inclined to think that it’s more likely for C-compatible enums to want to be non-exhaustive than it is for enums carrying associated values to want to be non-exhaustive.

So I guess I’m saying, I want more thought put on the topic of whether enums defined in Swift should actually default to non-exhaustive, and I’m now leaning towards the idea that they should remain exhaustive (but Obj-C enums will still default to non-exhaustive).


I don’t like that modules using @testable imports treat all enums as exhaustive. I can see why you want to do that, but being forced to handle non-exhaustive enums in unit tests seems like a valuable guard against accidentally publishing non-exhaustive enums that should be exhaustive.


I’m really not a fan of using a ‘default’ case in non-exhaustive enums. This means that if new cases are added, the compiler can’t help me find my switches. I’d really like to have an alternative way of saying “here’s how to behave in the event of an unknown enum case” without also making that a catch-all for unspecified-but-known cases. You already brought up this issue in the alternatives section, where you stated

> Ultimately I decided not to include this in the proposal with the expectation is that switches over non-exhaustive enums should be uncommon.

But since non-exhaustive enums will be the default, I think this _will_ become quite common, if for no other reason than you’re using a library written by someone who forgot to mark enums as @exhaustive that really should be.

Regarding the comment that a ‘future’ case is impossible to test, so is a ‘default’ case on a switch that is otherwise exhaustive. In the latter you can test it by commenting out one of your existing cases. But you can do that with ‘future’ too, just by renaming it to ‘default’ first.


In the “Use-side” section it says that a switch without a default case will produce a warning in Swift 4 mode. But in Swift 4 mode all enums are exhaustive by default and the @exhaustive annotation does nothing. These two things can’t both be true or else Swift 4 mode will emit warnings on switches over enums that are very clearly supposed to be exhaustive enums.
> Is the problem being addressed significant enough to warrant a change to Swift?
> Does this proposal fit well with the feel and direction of Swift?
> How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
A quick reading, followed by a few re-readings as I composed this email.

-Kevin Ballard
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20171219/eea3bd6e/attachment.html>

More information about the swift-evolution mailing list