I like this a lot. +1

Sent from my iPhone

> On Feb 7, 2017, at 21:22, Matthew Johnson <[email protected]> wrote:
> 
> 
>> On Feb 7, 2017, at 1:45 PM, Robert Widmann via swift-evolution 
>> <[email protected]> wrote:
>> 
>> I lean +1, but this answer on its own seems incomplete.  Exhaustiveness is 
>> an important property, and it’s not clear what happens here now when you 
>> fall through a “complete” case tree without matching a pattern, and in that 
>> sense this plan solves a problem.  But it also would hinder a “future-you” 
>> from going back and dealing with the ramifications of swapping a dependency 
>> for a newer version, in that with a default now covering the rest of the 
>> cases the compiler is unable to tell you which cases you are actually 
>> missing post-upgrade.
>> 
>> Library Evolution includes what I think is the more complete response here: 
>> An @closed attribute for enums where a switch is guaranteed to be 
>> exhaustive.  (Though, after the open discussion, I wonder if that keyword 
>> can’t be reused in some way to provide the inverse restriction instead).
> 
> I agree that we probably need to allow both and the question is whether we 
> have a default or not, and if we do, which one is the default.  
> 
> Personally, if we have a default I would prefer for the default to be closed. 
>  One of the most important attributes of enums is the fact that they 
> encompass a fixed set of known cases.  I *want* my code to break if a new 
> case is added to an enum of another module I depend on.  As the Library 
> Evolution document notes "adding new cases should not be done lightly. Any 
> clients attempting to do an exhaustive switch over all enum cases will likely 
> not handle new cases well.”.  Perhaps if a module author is not willing to 
> commit to a fixed set of cases maybe publicly exposing an enum’s cases is not 
> the best way to model the API in question.
> 
> I understand that making closed the default is the is slightly contrary to 
> the principle that a module author explicitly opts-in to public API 
> contracts.  With that in mind, I would also consider it acceptable to decide 
> that there should be *no* default, as we did in the `open` discussion.
> 
> It’s also worth noting that in the context of enums there are two ways in 
> which an enum might be considered open - open to future extension by the 
> module itself and open to extension by other modules.  The latter most 
> closely matches the meaning of the `open` access modifier as it is currently 
> used and I believe it has been requested on the list once or twice.  With 
> that in mind, I don’t think we should reuse the `open` keyword to mean “open 
> to extension in a future version of the module, but not open to extension by 
> users of the module”.  That is basically equivalent to the meaning of 
> `public` for classes.
> 
> This leads me to conclude that maybe the right answer here is to require 
> library authors to specify `closed` *or* `public` when exposing an enum 
> outside the module.  This follows the principle of library authors explicitly 
> opting in to public API contracts, but also does not penalize the library 
> author with additional verbosity for the contract which is more likely to 
> lead to correct client code.
> 
> 
>> 
>>> On Feb 7, 2017, at 10:12 AM, Tanner Nelson via swift-evolution 
>>> <[email protected]> wrote:
>>> 
>>> Hello Swift Evolution,
>>> 
>>> I'd like to propose that a warning be emitted when default cases are 
>>> omitted for enums from other modules. 
>>> 
>>> What this would look like:
>>> 
>>> OtherModule:
>>> ```
>>> public enum SomeEnum {
>>>     case one
>>>     case two
>>> }
>>> 
>>> public let global: SomeEnum = .one
>>> ```
>>> 
>>> executable:
>>> ```
>>> import OtherModule
>>> 
>>> switch OtherModule.global {
>>>     case .one: break
>>>     case .two: break
>>>     ^~~~~ ⚠︎ Warning: Default case recommended for imported enums. Fix-it: 
>>> Add `default: break`
>>> }
>>> ```
>>> 
>>> Why:
>>> 
>>> Allowing the omission of a default case in an exhaustive switch makes the 
>>> addition of a new case to the enum a breaking change. 
>>> In other words, if you're exhaustively switching on an enum from an 
>>> imported library, the imported library can break your code by adding a new 
>>> case to that enum (which the library authors may erroneously view as an 
>>> additive/minor-bump change).
>>> 
>>> Background:
>>> 
>>> As a maintainer of a Swift framework, public enums have been a pain point 
>>> in maintaining semver. They've made it difficult to implement additive 
>>> features and have necessitated the avoidance of enums in our future public 
>>> API plans.
>>> 
>>> Related Twitter thread: 
>>> https://twitter.com/tanner0101/status/796860273760104454
>>> 
>>> Looking forward to hearing your thoughts.
>>> 
>>> Best,
>>> Tanner
>>> 
>>> Tanner Nelson
>>> Vapor 
>>> +1 (435) 773-2831
>>> 
>>> 
>>> 
>>> 
>>> 
>>> 
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected]
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected]
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to