First, this is an extremely well-written proposal, that explains itself well 
and tries to walk a difficult tightrope.  So, A+ for that.

That said, I think it needs modification before acceptance:

* I agree with Dave DeLong that @exhaustive does not actually "do anything", it 
relies on library authors to do the right thing but library authors cannot be 
trusted.  I am not even sure Optional will continue to have its two cases based 
on the track record of the swift-evolution process :-P
* I agree with Vladimir S that app developers need to be able to use 
compile-time checks that they handle all the "known cases" for an arbitrary 
enum (e.g. exhaustive or non-exhaustive), for example with "future" or some 
other mechanism.  Lack of testability does not actually concern me, but I feel 
it could be addressed by allowing the assignment of Any to a non-exhaustive 
enum, perhaps gated via a warning or an @testable.

I feel that a better solution to the underlying dilemma would be the following:

* As an app developer, I can use switch! or @import! to mean that I am 
vendoring this SDK and the runtime library will definitely be the same library 
I am linking against.  So it does not matter if the library author intends to 
someday add more cases – from my point of of view they are exhaustive, because 
this is the library I am linking, accept no substitutes.  Cases are checked at 
import time, and there is a runtime exception if somebody swaps the binary for 
one with "new" cases, may god have mercy on their soul
* As an app developer, in the absence of one of those opt-in mechanisms an 
imported enum is assumed to be open and I must handle either a default case 
(which is not compile-time checked for exhaustion) or a future case (which is). 
 I prefer "undefined" for "future" as a keyword because it seems to me library 
authors can also remove cases, regardless of what this proposal says.

This solution is a nod to @clattner's "the difference between source packages 
and binary packages that are updated outside your control (e.g. the OS, or a 
dynamic library that is updated independently of your app like a 3rd party 
plugin)."  But he is wrong that the difference is somehow tied together with a 
notion of binary and source: it is a difference between whether the library is 
vendored or nonvendored, that is whether it is shipped with the application or 
the OS.  If it is shipped with your application, you control the updates and so 
all enums can be exhaustive, if it is shipped with the OS it is updated 
independently and who knows what cases will appear at runtime.  But there is no 
law that says I have the sourcecode for all my application's libraries or that 
OS vendors only ship binaries, so I use "vendored" and "non-vendored", and 
"import-time" for "compile-time" to be precise in this distinction.

As a library author, I am not sure that the @exhaustive promise is meaningful.  
Unlike resilience more generally where a library author can provide some 
fallback behavior for client who calls a deprecated method, there is really not 
much that can be done to support older clients who are unaware of my new enum 
case.  I suppose we could introduce compile-time checks to prevent passing that 
enum case to an older client, for example

public enum Foo {
    case old
    @introduced (1.1) case new

public final enum Fixed {
    case one
    @introduced (1.1) case two //error: Can't add a new case to a final enum, 
drop @introduced or drop final

public func bar() -> Foo {
    return .new //error: Not all clients support case new, use if #available or 

This sort of thing might be a justification for supporting a "final" or 
"exhaustive" declaration, but the motivation in this listing is to support 
library authors within their own compilation unit, rather than exposing a 
signal to app developers that may or may not be reliable moving forward.

As shown in this listing, I find "final" more natural and more in the spirit of 
Swift than @exhaustive.


On December 19, 2017 at 4:58:14 PM, Ted Kremenek ( wrote:

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:
or, if you would like to keep your feedback private, directly to the review 

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

Proposal link:
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?

Ted Kremenek
Review Manager
swift-evolution-announce mailing list
swift-evolution mailing list

Reply via email to