[swift-evolution] Enums and Source Compatibility - defaults

Rod Brown rodney.brown6 at icloud.com
Fri Aug 11 00:23:45 CDT 2017


Hi all,

I thought I’d chime in with my own 2c…

I’d probably prefer something more like “final” and vs non-final. It’s the concept we’re dancing around - can you add something to extend it?

In which case, final would allow exhaustive use, and non-final would require handling the default case. Currently all Swift API would convert as “final”, and all imported Obj-C API (with perhaps exceptions) would import as is and require a default handling case. This negates the open vs public issue. But it does also mean that it would become a manual issue inside the module to mark the API as final to allow exhaustive switches, unless we say “exhaustive switches allowed on internal/fileprivate/private types”.

Unsure how this plays into the web of things, though…

Thanks,

Rod



> On 11 Aug 2017, at 9:41 am, Jordan Rose via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
> 
>> On Aug 10, 2017, at 13:00, David Hart <david at hartbit.com <mailto:david at hartbit.com>> wrote:
>> 
>> 
>> 
>> On 10 Aug 2017, at 19:19, Jordan Rose <jordan_rose at apple.com <mailto:jordan_rose at apple.com>> wrote:
>> 
>>> 
>>> 
>>>> On Aug 9, 2017, at 22:46, David Hart <david at hartbit.com <mailto:david at hartbit.com>> wrote:
>>>> 
>>>> 
>>>>> On 10 Aug 2017, at 02:42, Jordan Rose <jordan_rose at apple.com <mailto:jordan_rose at 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 "closed".
>>>>> - 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.)
>>>>> 
>>>>> vs.
>>>>> 
>>>>> - 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 important):
>>>> 
>>>> * 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?
> 
> That's the "library evolution" criterion above, yes. But the behavior of enums inside the module doesn't need to affect what we do across modules.
> 
>> And what do you think of the idea of having the « exhaustiveness » modifier imply public, like open does?
> 
> I'm a little less sure about that. It does help with the keyword soup problem, but it's also not as obviously about access as "open" was, and "open" can also appear where other access modifiers can appear (on methods, properties, and subscripts).
> 
> Jordan
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170811/13b70d1b/attachment.html>


More information about the swift-evolution mailing list