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

Jordan Rose jordan_rose at apple.com
Wed Dec 20 13:16:45 CST 2017


Thanks for the feedback, Dave! Responses inline.

> On Dec 20, 2017, at 09:23, Dave DeLong via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
> 
>> On Dec 19, 2017, at 3:58 PM, Ted Kremenek via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs through January 3, 2018.
>> 
>> The proposal is available here:
>> 
>> 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>
>> When reviewing a proposal, here are some questions to consider:
>> 
>> What is your evaluation of the proposal?
>> 
> A very strong -1. I do not believe this is the appropriate solution to the problem.
> 
> • While the goal of the proposal is to ensure the correctness of *client* code, it does nothing to enforce the correctness of evolving *library* code. As a library author, I can declare a public enum as “exhaustive”, yet still add a new case in the next release. Nothing in the proposal prevents me from doing this, yet doing so would obviously break any clients of my library. 

There are some ideas listed to prevent this occurence in the proposal. Additionally, such a change may be desirable for a major version release of a library distributed as source. Nothing prevents someone from changing the type of an 'open' method either, but that can also be a breaking change.


> • The name “exhaustive” is misleading for uninformed library authors. An author creates an enum and then thinks “is that all of the cases? Yep! OK, it’s @exhaustive”. Then the next evolution of the library occurs, new cases arise, and now the enum isn’t exhaustive to handle the new cases. So a case gets added, and the formerly-but-not-actually-exhaustive enum is re-stamped as exhaustive, because it once again handles all known cases. “Exhaustive” is not a strong enough name. It does not contain the idea of eternal permanence. Once an enum gets branded as exhaustive and shipped as such, *it can never change*. “Exhaustive” does not imply that, and the lack of that implication will confuse library authors.

I don't think anyone loves the current name, but we haven't come up with a better one (cf. "Alternatives considered"). Any suggestions?

(As mentioned above, I also don't think this is an impossible situation either. But we'd certainly want people to not do it by accident.)



> • This proposal does not address the case of “publicly exhaustive enums with private cases”. Consider NSExpression.ExpressionType: when creating NSPredicates from format strings, it is easy to create sub-expressions whose expression types are not one of the publicly listed cases. Based on the proposal, NSExpression.ExpressionType would be correctly imported as a non-exhaustive enum. HOWEVER. There is nothing *stopping* a library author from declaring a publicly exhaustive enum (like NSExpression.ExpressionType), but having private cases that get leaked (accidentally or not) past the public barrier and end up in client code. This proposal does nothing to prevent that.

Swift does not currently support enums with private cases (as mentioned in the proposal), but if it did, such an enum could not be marked "exhaustive". On the C side, there's no way to check that no one's secretly using a private case, so we have to trust the author of the type to use the equivalent annotation responsibly.


> The summary of these objections is this: you fundamentally cannot trust libraries that are not bundled with your application to not change in unexpected ways. Or in other words, if you don’t have the source code, you cannot trust it. And even if you do have the source code, it’s still questionable once you start bridging things in from other languages where this sort of safety is not enforced.

This is fair, and we should consider leaving an implicit "default: fatalError()" in even for supposedly exhaustive enums (at least those imported from C).

Jordan


> 
> To summarize the summary: Leaving a judgement of “exhaustive or not” up to fallible library authors isn’t safe.
> 
> To summarize the summary of the summary: people are a problem.
>> Is the problem being addressed significant enough to warrant a change to Swift?
>> 
> Yes, the problem is significant, but in my opinion this is the wrong answer.
>> Does this proposal fit well with the feel and direction of Swift?
>> 
> No. Implementing this proposal would give the appearance of safety while still leaving developers subtly but dangerously vulnerable to imperfectly written libraries (ie, all of them).
>> How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
>> 
> I’ve been following the email threads, and I’ve spent years as a library author, both on Apple frameworks and my own personal libraries.
> 
> Dave
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20171220/8078519d/attachment.html>


More information about the swift-evolution mailing list