Okay I came to the conclusion that this won’t work that easily. Here is my 
reasoning why I think that way. If one assume for a second that one day we 
might have value sub typing - yes not now and not in the next Swift version, 
but hear me out please - we will come back and discuss the alignment of 
`open/public` for value types (including enums of course) which would allow us 
to create sub/supertypes of an enum from module A in module B with `open` 
modifier, where on the other hand `public` would restrict sub/supertyping to 
the module where the enum is defined, very similar to classes. Here is the 
tricky part now. If we’d add a `closed` modifier which implies `public` then we 
end up with a hole that cannot be filled at that point of time, because we 
would only be able to declare a public-but-open and a public-but-closed enum. 
However we still would need be able to create an open-but-open enum (lhs open 
is the constraints for sub typing, rhs open is the constraint that we talk 
about in this thread). Therefore to support open-but-open version we would 
require a special keyword.

I want to modify your main idea into:

(Potentially possible in the future)
- open-but-finite enum - or simply: open finite enum
- open-but-infinite enum - or simply: open enum

(Version that we could make possible in Swift 5)
- public-but-finite enum - or simply: public finite enum
- public-but-infinite enum - or simply: public enum

Am 10. August 2017 um 22:00:40, David Hart (da...@hartbit.com) schrieb:

On 10 Aug 2017, at 19:19, Jordan Rose <jordan_r...@apple.com> wrote:

On Aug 9, 2017, at 22:46, David Hart <da...@hartbit.com> wrote:

On 10 Aug 2017, at 02:42, Jordan Rose <jordan_r...@apple.com> wrote:

:-) As you've all noted, there are some conflicting concerns for the default:

- Source compatibility: the existing behavior for an unannotated enum is 
- Intuition: if you show someone an enum without an explicit annotation, 
they'll probably expect they can switch over it. (I'm going to say this is why 
Zach calls it a "sensible default".)
- Consistency: switches on an enum in the same module can always be exhaustive, 
so having it be different across modules is a bit annoying. (But 'public' 
already acts like this.)


- Library evolution: the default should promise less, so that you have the 
opportunity to change it.
- Flexibility: you can emulate an exhaustive switch with a non-exhaustive 
switch using fatalError, but not the other way around.

All of this is why I suggested it be an explicit annotation in either 
direction, but Matthew brought up the "keyword soup" problem—if you have to 
write (say) "public finite enum" and "public infinite enum", but would never 
write "private finite enum" or "private infinite enum", something is redundant 
here. Still, I'm uncomfortable with the default case being the one that 
constrains library authors, so at least for binary frameworks (those compiled 
"with resilience") I would want that to be explicit. That brings us to one more 
concern: how different should binary frameworks be from source frameworks?

In terms of intuition and consistency, I think we should really try to learn 
from the simplicity of public/open:

* When internal, classes are sub-classable by default for convenience, but can 
be closed with the final keyword
* When public, classes are closed to sub-classing for safety, but can be opened 
up with the open keyword (which implies public).

If we try to mirror this behaviour (the keywords are just suggestions, not 

* When internal, enums are exhaustive by default for convenience, but can be 
opened-up with the partial keyword
* When public, enums are non-exhaustive by default for safety, but can be made 
exhaustive with the exhaustive keyword (which implies public).

This is not a correct understanding of the internal/public distinction for 
classes, though. From inside a module, a public-but-not-open class is still 
subclassable, and similarly a public-but-not-"closed" enum will still be 
exhaustively switched. You don't have to worry about your own module changing 
out from under you.

Correct. Thanks for the clarification! But you still agree with the argument, 
right? Convenience for same module enums (exhaustive by default), safety for 
clients of the module (not-exhaustive when public from outside the module), 
with the option to be explicit? And what do you think of the idea of having the 
« exhaustiveness » modifier imply public, like open does?


swift-evolution mailing list

Reply via email to