SE-0192 — Non-Exhaustive Enums


(Ted Kremenek) #1

The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs through January 3, 2018.

The proposal is available here:


Reviews are an important part of the Swift evolution process. All review feedback should be sent to the swift-evolution mailing list at:

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager.

When replying, please try to keep the proposal link at the top of the message:

Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
...
Reply text
...
Other replies
What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

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?

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Thanks,
Ted Kremenek
Review Manager


Inlinable initializers vs. property initial value expressions
SE-0192 — Non-Exhaustive Enums — review #2
(Lily Ballard) #2

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).

···

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

--

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?

Yes

Does this proposal fit well with the feel and direction of Swift?

Yes

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


(Howard Lovatt) #3

As an aside: there seems to be increasingly comments about proposals that say:

  1. This was discussed at the evaluation stage and rejected.
  2. This is how it is implemented in the patch.

And other comments along those lines. Neither the pre-proposal discussions nor the proposed implementation are intended to limit the scope of the review. Therefore I don’t think people should raise this as reasons. You should remember that the process is deliberately staged this way and different people may well be commenting (in fact the process rather assumes that people in the formal review will be a wider set of people).

Anyway gripe over.

Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
What is your evaluation of the proposal?

+1/2

I only give this a half because whilst it is important I can see three issues:

  1. It doesn’t seem very Swift like to have a different rule, default non-exhaustive, for public as opposed to non-public.

  2. It doesn’t seem very Swift like to have the default the unsafe case.

  3. Other languages have better solutions - see below under other languages

Is the problem being addressed significant enough to warrant a change to Swift?

Yes, Swift ABI compatibility going forwards is important

Does this proposal fit well with the feel and direction of Swift?

No. As mentioned above different rules for public and a non-safe default don’t see that Swift like.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

Both Java and Scala have a better solution. In these languages enums (Scala calls them case classes) can implement protocols and the user of an enum rarely writes a switch statement, instead they call protocol methods. Enums in these languages are a fixed set of derived classes; i.e. normal OO programming rather than functional programming, which works well in the case of wanting to expand later the number of enum cases.

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Have followed the discussions. Used enums in Swift and other languages extensively.

-- Howard.

···

On 19 Dec 2017, at 12:58 pm, Ted Kremenek <kremenek@apple.com> wrote:

When replying, please try to keep the proposal link at the top of the message:

Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
...
Reply text
...
Other replies
What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

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?

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?


(Ethan Diamond) #4

Hello everyone,

One major pain point I've run into with Swift is the inability to evaluate
the case of an enum that has associated values in a way that just returns a
bool. We've been given the ability in a switch statement:

enum Enum {
   case a(param: String)
   case b(param: String)
}

let enumeration: Enum = a(param: "Hi")
switch enumeration {
    case a:
      // Do something
    case b:
      // Do something
}

We'e been given the ability in the context of an if statement:

enum Enum {
   case a(param: String)
   case b(param: String)
}

let enumeration: Enum = a(param: "Hi")

if case .a = enumeration {
    // Do something
}

But without a basic was of getting a bool for if an enum is a given case,
here's a list of things I can't do:

*Where statements:*

enum Enum {
   case a(param: Enum2)
   case b(param: Enum2)
}

enum Enum2 {
    case c(param: String)
    case d(param: String)
}

let enumeration: Enum = a(param: "Hi")
switch enumeration {
    case a(let inner) where [INNER CASE IS .c]
}

···

---------

*Filter an array for a certain case:*

Expertly explained by Erica Sadun here:
http://ericasadun.com/2017/01/31/challenge-filtering-associated-value-enumeration-arrays/

---------

*Nicely set a UIButton to hidden if an enum is a certain case:*

enum State {
    case `default`
    case searching(results: [Result])
}

myButton.isHidden = [STATE IS .searching]

---------

I've run into this issue a ton of times because I tend to represent my
views a State enums. I haven't seen anything on the board for plans for
solving this issue, thought. Has there been any discussion about addressing
it? Ideally I'd be able to do this:

enum Enum {
   case a(param: String)
   case b(param: String)
}

let enumeration: Enum = a(param: "Hi")

case .a = enumeration // Bool
case .a(let param) = enumeration // Bool, assigns "Hi" to "param"

Thanks!
Ethan


(Sebastian Hagedorn) #5

What is your evaluation of the proposal?

+1 if a `future` case (or similar solution… “unknown” might be a nice keyword, although some enums probably have an `.unknown` case which could be confusing) is added.

Is the problem being addressed significant enough to warrant a change to Swift?

I guess so – I understand this is a real issue for binary libraries (so basically, Apple).

I don’t think it’s an issue for open source libraries. Forcing the clients to update their code when they update the library (which they can do when they choose to, usually) seems reasonable to me, compared to the risk of not handling the new cases.

Does this proposal fit well with the feel and direction of Swift?

I don’t mind the default and I believe it’s ok to leave it to the library author to decide whether or not an enum should be exhaustive.

That said, I don’t think “you need to add a default case” feels very Swifty. It forces you to write code that you essentially have no idea about, so I would assume I’d just always put in an assert so I notice it in debug/beta builds, and keep my fingers crossed ignoring the unknown case doesn’t do any harm in release builds.

I strongly disagree with this:

The expectation is that switches over non-exhaustive enums are uncommon.

Basically every time I interact with an enum, I switch over it, to make sure I don’t forget anything, and to make sure I reconsider my code if the library changes. Since most SDK enums will become non-exhaustive, this is the 99% case for me.

Re: the future case: I don’t expect to actually put any code in there. If it’s code I intend to run in any case, it will typically be outside of the switch statement. Since the semantic of the new case is unknown to me, what code should I write to handle it? For that reason, I don’t think testability is a real issue here. I believe the limitation for single-value matching is fine for now, and could probably be extended to something like `case (true, future)`.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

No.

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Carefully read the proposal and followed some of the previous discussions.

···

On 19. Dec 2017, at 23:58, Ted Kremenek <kremenek@apple.com> 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
Reviews are an important part of the Swift evolution process. All review feedback should be sent to the swift-evolution mailing list at:

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager.

When replying, please try to keep the proposal link at the top of the message:

Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
...
Reply text
...
Other replies
What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

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?

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Thanks,
Ted Kremenek
Review Manager
_______________________________________________
swift-evolution-announce mailing list
swift-evolution-announce@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution-announce


Discourse hijacks ⌘F
(Dave DeLong) #6

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
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.

• 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.

• 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.

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.

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

···

On Dec 19, 2017, at 3:58 PM, Ted Kremenek via swift-evolution <swift-evolution@swift.org> wrote:


(Jerome Duquennoy) #7

Hi guys,

I am part of the people mentioned in "Preserve exhaustiveness diagnostics for non-exhaustive enums" : I see the completeness check as a major feature of enums, that makes a difference between it and a list of constants in multiple cases.
So much that in the coding rules of the company I work for, the use of default case requires some specific justification at review time.

I have a positive opinion on this evolution if it comes with a solution to preserve exhaustiveness diagnostics. Otherwise, I think it lowers the ease of maintenance of code using external libraries.

One of the risk I fear is that libraries builders might just forget to add the @exhaustive keyword. So it might end up being a pretty common case to have to specify "I want this switch to be exhaustive", just to not loose on maintainability. This could lead to a situation similar to the "fileprivate", that ended up being used much more than expected.

It is not exactly in the scope of that review, but in the two solution for enforcing exhaustiveness drafted in that proposal, I would rather avoid the second one (the switch!). It would contradict the fact that as of today, the use of the exclamation mark in swift is a pretty clear sign that you are disabling some compiler-provided security at your own risk, and that it might lead to runtime crash (force unwrap, force cast, ...).
Here, requesting a switch to be exhaustive is adding one more compiler check. It cannot lead to a runtime crash.
I will be happy to discuss it further in a future review.

Jerome


(Jon Hull) #8

When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

Strong -1 as is.

I think I would support having an explicit ‘futureCase’ which is different from ‘default’. Requiring default is asking for bugs. With a separate ‘futureCase’, we would still get a compile-time error when all of the current cases aren’t handled. Note that ‘ futureCase’ is also different than ‘default’ in that it wouldn’t have to go at the bottom. It would only be triggered when the value isn’t one of the values which was known at compile time. We should also bike shed the name of ‘futureCase’ to come up with something that might allow us to make other types of extendable enums…. Maybe something like ‘unknownCase’ or ‘unexpectedCase’.

As for the issue of testing, we could add (later) a universally unexpected case that non-exhaustive enums can be set to for testing. I am not convinced that this is actually a big enough issue to warrant that though. Forcing ‘default’ is a much larger real-world problem, IMO (and this use of ‘default’ is just as untestable).

I also dislike the name @exhaustive because I think it will cause confusion (i.e. “Of course my Enum is exhaustive”). I think we should just have @fixed for both enums and structs. The word fixed has the connotation that it shouldn’t change.

Is the problem being addressed significant enough to warrant a change to Swift?

Yes, I think the problem is significant, but this is not the correct solution.

Does this proposal fit well with the feel and direction of Swift?

Not quite. While I think ABI safety is Swifty, I feel like this design actually encourages a lack of safety in other areas. Much better to explicitly deal with the issue of added/future cases in code than to hide it with ‘default’.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

I have used Enums in several languages, but Swift is the only one which has required exhaustive enums… I have a hard time going back to languages which don’t have it now.

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Thoroughly read proposal, casually followed the original discussion.

Thanks,
Jon

···

On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution <swift-evolution@swift.org> wrote:


(Colin Barrett) #9

I very much agree with the motivations for this proposal. It identifies a clear, urgent need.

I disagree that the proposed solution is a good solution. It makes a very significant, and confusing, change to the language that does not have much precedent in other languages. This goes against the stated design guidelines for the Swift language.

I would much rather see Swift follow the lead of other ML languages and introduce something like “polymorphic variants”[1] or Standard ML’s exceptions (which are "open” in this way by default)

Thanks for everyone's hard work, particularly the authors,
-Colin

[1]: https://realworldocaml.org/v1/en/html/variants.html#polymorphic-variants
[2]: https://www.cs.cmu.edu/~rwh/introsml/core/exceptions.htm

···

On Dec 19, 2017, at 5:58 PM, Ted Kremenek via swift-evolution <swift-evolution@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
Reviews are an important part of the Swift evolution process. All review feedback should be sent to the swift-evolution mailing list at:

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager.

When replying, please try to keep the proposal link at the top of the message:

Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
...
Reply text
...
Other replies
What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

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?

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Thanks,
Ted Kremenek
Review Manager
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Letanyan Arumugam) #10

What is your evaluation of the proposal?

+1 it solves an important problem in our ecosystem.

Is the problem being addressed significant enough to warrant a change to Swift?

Yes

Does this proposal fit well with the feel and direction of Swift?

This is weird because I feel that having @exhaustive as the default would be more inline with the feel of Swift, but the current default is better for usability.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

Have not used a similar feature.

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Read the proposal and a little bit of research into the links from the proposal.


(Karl) #11

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
Reviews are an important part of the Swift evolution process. All review feedback should be sent to the swift-evolution mailing list at:

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager.

When replying, please try to keep the proposal link at the top of the message:

Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
...
Reply text
...
Other replies
What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

+1, it needs to happen (and ASAP, since it _will_ introduce source-breaking changes one way or the other).

I think non-exhaustive is the correct default. However, does this not mean that, by default, enums will be boxed because the receiver doesn’t know their potential size? That would mean that the best transition path for multi-module Apps would be to make your enums @exhaustive, rather than adding “default” statements (which is unfortunate, because I imagine when this change hits, the way you’ll notice will be complaints about missing “default” statements).

I do have some thoughts about how we could ease the transition (for this and other resilience-related changes), but it’s best to leave that to a separate discussion.

The one thing I’m still not overly fond of is the name - I would like us to keep the set of resilience/optimisation related keywords to a minimum. “exhaustive” for enums feels an awful lot like “fixed_contents” for structs - couldn’t we come up with a single name which could be used for both? I don’t think anybody’s going to want to use “exhaustive” for structs.

Is the problem being addressed significant enough to warrant a change to Swift?

Definitely. Major part of ABI stability.

Does this proposal fit well with the feel and direction of Swift?

It does indeed.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

I can’t remember making much use of exhaustive enums before Swift.

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Followed earlier discussions, read the proposal and comments so far. Even gave it a bit of thought, which was refreshing.

···

On 19. Dec 2017, at 23:58, Ted Kremenek via swift-evolution <swift-evolution@swift.org> wrote:
Thanks,
Ted Kremenek
Review Manager
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Ash Furrow) #12

Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md

What is your evaluation of the proposal?

-1.

Is the problem being addressed significant enough to warrant a change to Swift?

I’m afraid not.

This appears to be a solution to a non-existing problem. I worry that making this change will alienate developers from Swift and I caution against accepting it.

Does this proposal fit well with the feel and direction of Swift?

It may have at one time point in time, but not now.

The chaotic churn of the language, the syntax, and the standard library is supposed to be behind us. We need to accept that things fell into place as they did, often in imperfect ways. We probably could correct all the imperfections, but when would we ever stop? Language churn has a cost. This proposal is something that I could definitely see being a part of Swift 2 or Swift 3, but we have already decided that enums are exhaustive. This change, and changes fundamental to the cognitive model Swift programmers already have of their tool, need to be heavily weighted against language churn

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

Scala’s match syntax bears a striking resemblance to Swift’s switch syntax; however, Scala does not require exhaustive cases. If the developer does not include a default case and none of the cases match the expression, an exception is thrown. Because of Swift’s error-handling model, I don’t know that this behaviour would be desirable either (though I will say it makes sense in Scala).

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

I read most of the proposal (okay I skimmed some of the nitty-gritty, but I read to the end of “Source compatibility”) as well as looked over the pre-review threads and skimmed GitHub pull request thread.

···

From my perspective as a Swift user, this change represents nontrivial language churn without providing a solution to a problem I have. The proposal doesn’t describe any benefits to me as an open source library maintainer or as a Swift developer. With earnest respect, the motivation section reads like “enums grow sometimes, but we like to exhaustively switch over them, so wouldn’t it be cool if …”, which is only a theoretical motivation. It fails to describe how and why this proposal would improve my Swift code or my experience using Swift.

--
Ash Furrow
https://ashfurrow.com/

On December 19, 2017 at 5:58:14 PM, Ted Kremenek via swift-evolution (swift-evolution@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
Reviews are an important part of the Swift evolution process. All review feedback should be sent to the swift-evolution mailing list at:

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager.

When replying, please try to keep the proposal link at the top of the message:

Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
...
Reply text
...
Other replies
What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

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?

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Thanks,
Ted Kremenek
Review Manager
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Vladimir) #13

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

Reviews are an important part of the Swift evolution process. All review feedback should be sent to the swift-evolution mailing list at:

    https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to the review manager.

When replying, please try to keep the proposal link at the top of the message:

    Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
    ...
    Reply text
    ...
    Other replies

      What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

  *

    What is your evaluation of the proposal?

+0.5.
I'll give additional +0.5 if 'future' case will be included in proposal.

I still do believe that without 'future' case we are introducing now a bug-generator point of code. For me this is obvious. Especially for the moment when Swift 4 code will be converted to Swift 5 and, as I understand, developer will see "non-exhaustive enum, add 'default' case" as suggestion during the migration. Instead of "use 'default' or 'future' ", so one can think and decide what needed here.

Having a tool('future' case) to express "switch over non-exhaustive enum exhaustively and let me know if new cases appear" is IMO a Swifty way, and much better than catching *run-time* bugs when your framework introduced a new enum value but you were not able to process it *during the compilation*, because you have 'default' case in switch.

Also, probably I missed this and not sure if this even can work, if framework(module) was compiled with Swift4 and contains 'public enum' - will such enum be treated as exhaustive if framework is imported in Swift 5 code? So, it was declared without @exchaustive, but for Swift4 exhaustive was the default.

Additionally, I'd like someone answers/comments my question regarding real-world example noted in the proposal (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171002/040053.html).
Is it really a very rare use-case for embedded framework&enums, and is it really I have to find a way to use lint-like tools to check new cases in embedded enum after proposal is implemented? Or use other technique to process all cases of enum declared in framework?

  *

    Is the problem being addressed significant enough to warrant a change to Swift?

Yes, I believe so.

  *

    Does this proposal fit well with the feel and direction of Swift?

Generally yes, but
* I don't like @exchaustive as attribute, something like "public sealed enum" or "public enum(final)" IMO is more Swifty syntax
* not safe/dangerous 'default' without able to keep switch exhaustive at compilation time IMO is not Swift-way

  *

    If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to
    those?

  *

Don't know

    How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Previous discussions, proposal text and proposal review thread

···

On 20.12.2017 1:58, Ted Kremenek via swift-evolution wrote:

Thanks,
Ted Kremenek
Review Manager

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Brent Royal-Gordon) #14

  • What is your evaluation of the proposal?

I am pleased with the broad strokes of this design. I have quibbles with three areas:

1. The `@exhaustive` attribute may be confusing because the term doesn't suggest versioning. My best alternative suggestion is `@frozen`, which matches existing programming terminology: something that has been frozen will not be changed in the future.

2. I think we need some kind of `future` keyword in `switch` statements. Even though a nonexhaustive enum may gain additional cases in the future, it's still useful for the compiler to diagnose that you forgot *known* cases.

You say that "switches over non-exhaustive enums should be uncommon", and this is true for many—perhaps most—non-exhaustive enums, but there is still a large class of non-exhaustive enums which need to be switched over. These are the ones I called "category 2" in my previous email in this thread. `SKPaymentTransactionState` is the example I previously used; others might include `Stream.Status` (if not exhaustive), `CLAuthorizationStatus`, `EKParticipantType`, `PKPaymentMethodType`, and `MKMapType`. Each of these could plausibly have more cases added; each has a good reason why you might switch over cases (such as display in a user interface); and each ought to be promptly updated when a new OS version introduces new cases. Without compiler assistance, those updates won't happen.

If we plan to add private cases in a future version of Swift, `future` may not be the best keyword. `unknown`, `invalid` (or `case #invalid`), etc. may be better.

3. I am very skeptical of treating all enums as exhaustive if imported by `@testable import`. The only reason I can see not to do this is that forcing you to provide `default` might hide tests that need to be updated for new enum cases—but this is the exact problem that `future` is trying to solve. By contrast, treating them as non-exhaustive forces you to actually notice when an enum is published as nonexhaustive and consider whether that's the right approach.

None of these are showstoppers if left unaddressed, but I think the design would be better if we fixed them.

  • Is the problem being addressed significant enough to warrant a change to Swift?

Yes. I have no idea how Swift programs currently behave when a future framework version adds a case, but I can't imagine they do anything good.

  • Does this proposal fit well with the feel and direction of Swift?

Yes, with the exception of conflating `default` and `future`, which removes useful correctness checks.

  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

I've experienced bugs in Objective-C caused by the compiler not knowing an enum might have additional, unknown cases. Debugging them sucked.

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

I've participated in multiple rounds of discussion on this topic, and read the proposal top-to-bottom for this review.

···

On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution <swift-evolution@swift.org> wrote:

--
Brent Royal-Gordon
Architechies


(Chéyo Jiménez) #15

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
Reviews are an important part of the Swift evolution process. All review feedback should be sent to the swift-evolution mailing list at:

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager.

When replying, please try to keep the proposal link at the top of the message:

Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
...
Reply text
...
Other replies
What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

+1 except for the name. @frozenExposed @fixedMembers @frozenMembers.
preferably something that aligns with the other notion of not being able to add public members to structs. This will help treat structs with static members in the same way which would be ideal. I don't think enums should have their own attitude.

Is the problem being addressed significant enough to warrant a change to Swift?

don't know. im not a library author. ill defer to other library authors.

Does this proposal fit well with the feel and direction of Swift?

yes.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

n/a

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

followed the previous discussion. read the proposal.

···

On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution <swift-evolution@swift.org> wrote:
Thanks,
Ted Kremenek
Review Manager
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Chris Lattner) #16

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
When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

I'm strongly in favor of it. This is important to resolve as part of the ABI stability and binary frameworks projects which are top goals of Swift 5.

Is the problem being addressed significant enough to warrant a change to Swift?

Yes.

Does this proposal fit well with the feel and direction of Swift?

Yes, absolutely, in a couple of ways:

- This design abides by the goal of progressive disclosure: you’re completely unaffected by it (and don’t have to think about it) until you are publishing a public enum outside of your module.
- This is a "safe default”: if someone forgets to think about how their enum will be used, it will design to being non-exhaustive. If this becomes a problem in practice for their clients, they’d get notified of that and can (without breaking abi compatibility with previous releases) opt into exhaustiveness. If the parity is reversed, this won’t be the case.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

Swift is an uncommon language because it aims to support both static compilation and long-term API/ABI stability. Many other languages choose one over the other: e.g. C++ is good at static compilation, but not long-term API/ABI stability (fragile base class problem, and C enums, etc). Java is good at long-term API stability, but not great for static compilation.

The closest analog I’m familiar with is the Objective- part of Objective-C, which is great at API/ABI stability . Unfortunate, it inherited its enum model from C, and we are well aware of how problematic they are for framework evolution. This approach is a great solution to the problems found through decades of experience evolving APIs that use these C enums.

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

A lot of time.

-Chris

···

On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution <swift-evolution@swift.org> wrote:


(Kevin Nattinger) #17

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
What is your evaluation of the proposal?

I was going to say -100 without future, +1 with, but other arguments on this thread have put me on the fence to mildly against, so -100 without future, -ε with.

In the proposal, there is the following text:

The consequences of losing exhaustiveness checking for non-exhaustive enums are discussed in the "Alternatives considered" section at the end of this proposal.

A number of pre-reviewers have been concerned about the loss of exhaustiveness checking and the subsequent difficulty in updating to a new version of a dependency. In the original swift-evolution thread, Vladimir S. describes the concerning scenario <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171002/040053.html> in detail.

I find it deeply disturbing that this scenario is acknowledged as "concerning" and yet ignored without justification in the proposal proper, and in the "alternatives" dismissed solely based on a baseless assumption—that the situation will be "uncommon." Even if it were an uncommon case, the negative impact is still dire enough and without a good workaround that I'd argue strongly that the concern be addressed properly.

The justification put forward to reject a `future` case is that "The expectation is that switches over non-exhaustive enums are uncommon." However, there is no evidence to support that assertion, and there are a huge number of enums in even just Apple's frameworks that people reasonably can, and in some cases really should, switch over. Go through any of the iOS frameworks and find authorization enums and delegates with enums in a callback, and you're likely to find some that it makes sense for a client to switch over. Just a few off the top of my head that I have personally switched on:

CoreBluetooth
- CBManagerState
- CBPeripheralManagerAuthorizationStatus
- CBPeripheralState
CoreLocation
- CLAuthorizationStatus
- CLActivityType
CoreData
- NSFetchedResultsChangeType
MessageUI
- MessageComposeResult
UIKit
- UITableViewCellEditingStyle

Every framework that requires user permission has its own authorization enum, many have an additional state enum, and for most delegate callbacks with an enum argument it's often a good idea to switch over the cases.

As a real-life example above and beyond the one referenced above, In the fairly small codebase I'm working in at the moment, I count a bit over 12klocs, 80-ish switches, and 6 switches that would need a `future` case (non-exhaustive, from Apple frameworks). That's about one per 2klocs, It probably wouldn't scale linearly in larger projects, but just their prevalence in the apple frameworks as I pointed out above would suggest it does grow significantly.

The extra onus on project authors required by not including a future case for those cases would make upgrading libraries and iOS versions incredibly difficult and error-prone. To ensure correctness, you would have to go over every single switch in your app, figure out the type it's switching on, and if the type is external and nonexhaustive, check that there are no new cases. Even if this is "not expected to be the common case," omitting the `future` means you have to either keep track of where all your relevant switch statements are and check them on every upgrade, go through and evaluate every switch statement to figure out whether you need to check for extra cases, or go through the API diff, find any added enum cases, and find every switch in your codebase that switches on them. All three options are dangerously error-prone and unacceptable.

In summary, failing to include a future case but requiring default instead would place an unacceptable burden on every nontrivial project every time a library is upgraded and (and I don't say this lightly) would almost certainly be the biggest mistake the Swift community has ever made.

There is an existing implementation along with the PR, so has anyone tried this change a project of significant size that uses a variety of Apple frameworks? How many `default`s did you have to put in that should be `future`, and how would you feel about having to find all those places again and any more that may be put in in a year or two *without* compiler checking?

Is the problem being addressed significant enough to warrant a change to Swift?

The problem needs to be addressed, certainly.

Does this proposal fit well with the feel and direction of Swift?

With future, sure. Without, absolutely not. As demonstrated and even acknowledged but dismissed without justification, it introduces an enormous issue with compile-time safety.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

N/a

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

I kept maybe half an eye on the original thread, but read the proposal and other posts in this review thread thoroughly.

···

On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution <swift-evolution@swift.org> wrote:
Thanks,
Ted Kremenek
Review Manager
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(David Owens) #18

I very much agree with the high-level of the proposal. The concept definitely needs to exist. However, I feel that the options presented do so in a non-intuitive way.

There are two concepts here: closed and open listing of values that make up a set of possible options to be used. I think of this much like struct vs. class in terms having to determine conceptually which is the right approach for the problem you are solving. As such, I feel that this is a significant enough difference between the concepts that it warrants a declarative difference via a keyword, not just some annotation.

Further, for me personally, putting conditional differences on access level has always been a very annoying and frustrating experience in Swift, and this adds to that. Using a keyword to distinguish helps with that.

I don’t know the best spelling for, but I’d want something like this:

enumset GregorianWeekday
{
    case monday // ISO 8601 says weeks start on Monday
    case tuesday
    case wednesday
    case thursday
    case friday
    case saturday
    case sunday
}

That’s the exhaustive list, no others can be added. Access level does not matter.

enum Emotions
{
    case happy
    case sad
    case angry
}

This is a non-exhaustive list. Others can be added via extensions. Access level does not matter.

-David

···

On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution <swift-evolution@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
Reviews are an important part of the Swift evolution process. All review feedback should be sent to the swift-evolution mailing list at:

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager.

When replying, please try to keep the proposal link at the top of the message:

Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
...
Reply text
...
Other replies
What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

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?

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Thanks,
Ted Kremenek
Review Manager
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Chris Eidhof) #19

I can see why this is useful, and understand the problem. However, it does
feel like the wrong solution to a real problem. This seems to be very
similar to the *expression problem*:

The expression problem is a new name for an old problem.[2][3] The goal

is to define a datatype by cases, where one can add new cases to the
datatype and new functions over the datatype, without recompiling existing
code, and while retaining static type safety (e.g., no casts).

(source: https://en.wikipedia.org/wiki/Expression_problem)

The price we'll pay for this proposal is to always have a default case with
non-exhaustive enums. To me, this feels very similar to the default case in
Swift's error handling, and in that sense it matches the existing language
behavior. However, I find the default case in Swift's error handling quite
annoying (especially if you can guarantee you've handled all possible
errors).

In the case of enums, I'd much rather get a compiler error because I didn't
handle case, than a runtime error because my default caught a case I
actually wanted to catch. Having non-exhaustive enums makes it much harder
to refactor code that uses those enums (if I add a case, the compiler
doesn't give me a list of all the sites I need to fix).

A -1 from me.

I would like a solution to the problem, but I feel that the proposed
solution has too many drawbacks.

···

On Tue, Dec 19, 2017 at 11:58 PM, Ted Kremenek <kremenek@apple.com> 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

Reviews are an important part of the Swift evolution process. All review
feedback should be sent to the swift-evolution mailing list at:

https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to the
review manager.

When replying, please try to keep the proposal link at the top of the
message:

Proposal link: https://github.com/apple/swift-evolution/blob/master/
proposals/0192-non-exhaustive-enums.md
...
Reply text
...
Other replies

What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review
through constructive criticism and, eventually, determine the direction of
Swift.

When reviewing a proposal, here are some questions to consider:

   -

   What is your evaluation of the proposal?
   -

   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?
   -

   If you have used other languages or libraries with a similar feature,
   how do you feel that this proposal compares to those?
   -

   How much effort did you put into your review? A glance, a quick
   reading, or an in-depth study?

Thanks,
Ted Kremenek
Review Manager

_______________________________________________
swift-evolution-announce mailing list
swift-evolution-announce@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution-announce

--
Chris Eidhof


(Rod Brown) #20

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
Reviews are an important part of the Swift evolution process. All review feedback should be sent to the swift-evolution mailing list at:

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager.

When replying, please try to keep the proposal link at the top of the message:

Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
...
Reply text
...
Other replies
What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

+1. I was involved in some of the earlier discussions and discussed the pros and cons of each way, tossed and turned, and to be honest, like “public vs open” I think this comes out to “it’s the best compromise”.

We need to handle additional cases safely, and people need to think carefully as it will be a compatibility issue to leave new enum cases unhandled. This proposal sums this up well.

Is the problem being addressed significant enough to warrant a change to Swift?

Yes. This is an important change.

Does this proposal fit well with the feel and direction of Swift?

Feel? Not 100%, but this is a compromise for compatibility. Direction? Yes. It is in a direction to allow ABI compatibility, so yes.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

I’ve dealt with not handling extra cases in Obj-C, and handling the compatibility issues with current Swift code.

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Somewhere between a quick reading and a in-depth study. This was one of my bugbears, something I knew we needed to sort out and I’m glad Jordan picked it up. I was involved in the conversation, and churned through the issues there in the earlier discussions.

···

On 20 Dec 2017, at 9:58 am, Ted Kremenek via swift-evolution <swift-evolution@swift.org> wrote:
Thanks,
Ted Kremenek
Review Manager
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution