> On Jan 3, 2018, at 11:49 AM, Dave DeLong <sw...@davedelong.com> wrote:
>> On Jan 3, 2018, at 10:36 AM, Matthew Johnson <matt...@anandabits.com 
>> <mailto:matt...@anandabits.com>> wrote:
>>> On Jan 3, 2018, at 11:07 AM, Dave DeLong via swift-evolution 
>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>> IMO this is still too large of a hammer for this problem.
>>> This whole “unexpected case” thing is only a problem when you’re linking 
>>> libraries that are external to/shipped independently of your app. Right 
>>> now, the *only* case where this might exist is Swift on the server. We 
>>> *might* run in to this in the future once the ABI stabilizes and we have 
>>> the Swift libraries shipping as part of iOS/macOS/Linux. Other than this, 
>>> unexpected enum cases won’t really be a problem developers have to deal 
>>> with.
>>> Because this will be such a relatively rare problem, I feel like a syntax 
>>> change like what’s being proposed is a too-massive hammer for such a small 
>>> nail.
>>> What feels far more appropriate is:
>>> 🅰️ Teaching the compiler/checker/whatever about the linking semantics of 
>>> modules. For modules that are packaged inside the final built product, 
>>> there is no need to deal with any unexpected cases, because we already have 
>>> the exhaustiveness check appropriate for that scenario (regardless of 
>>> whether the module is shipped as a binary or compiled from source). The app 
>>> author decides when to update their dependencies, and updating those 
>>> dependencies will produce new warnings/errors as the compiler notices new 
>>> or deprecated cases. This is the current state of things and is completely 
>>> orthogonal to the entire discussion.
>> John McCall sketched out a vision of what a solution to this might look like 
>> here: 
>> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171218/042333.html
>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171218/042333.html>.
>>> and
>>> 🅱️ Adding an attribute (@frozen, @tangled, @moana, @whatever) that can be 
>>> used to decorate an enum declaration. This attribute would only need to be 
>>> consulted on enums where the compiler can determine that the module will 
>>> *not* be part of the final built product. (Ie, it’s an “external” module, 
>>> in my nomenclature). This, then, is a module that can update independently 
>>> of the final app, and therefore there are two possible cases:
>>>     1️⃣ If the enum is decorated with @frozen, then I, as an app author, 
>>> have the assurance that the enum case will not change in future releases of 
>>> the library, and I can safely switch on all known cases and not have to 
>>> provide a default case. 
>>>     2️⃣ If the enum is NOT decorated with @frozen, then I, as an app 
>>> author, have to account for the possibility that the module may update from 
>>> underneath my app, and I have to handle an unknown case. This is simple: 
>>> the compiler should require me to add a “default:” case to my switch 
>>> statement. This warning is produced IFF: the enum is coming from an 
>>> external module, and the enum is not decorated with @frozen.
>> This does not help people who need to write a switch statement over an enum 
>> vended by a module that ships with the OS keep their code up to date as the 
>> module adds new cases. I find the example of `SKPaymentTransactionState` 
>> provided by Brent Royal-Gordon here: 
>> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170904/039512.html
>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170904/039512.html>
>>  to be compelling.  There are rare but legitimate reasons to switch over all 
>> known cases of a non-@frozen enum that ship with the OS.  These use cases 
>> deserve proper language support.  I think Jordan’s solution strikes a good 
>> balance.
> I disagree that more is needed. In the case of the transaction state, it 
> should not be marked as @moana, and so the compiler would force you to add a 
> “default” case to your switch statements. The switch statements would still 
> be exhaustive with all known cases (if you choose to handle all known cases), 
> but you’d still need a default case because there might be new transaction 
> states in the future.
> In those cases, your app could decide what to do, if that’s possible at all. 
> Maybe there’s other transaction information you could introspect to determine 
> if it succeeded or is still pending or whatever, and then your app could 
> respond as you see fit.

SKPaymentTransactionState is an excellent motivating example for a better 
solution because it is crucial to update code to handle any new states 
accurately and promptly.  This is much easier to do with compiler assistance 
than without it. 

It is also an excellent motivating example because the API change is driven by 
a business change and for which all states should be reflected accurately in 
the UX.  Apps need to switch over this enum as exhaustively as possible while 
the StoreKit team also needs to reserve the right to add cases as business 
requirements change.  

It is an evolution problem without a great answer.  I think Jordan has landed 
on a pretty good compromise.  If you don’t want a warning when modules change 
you’re still free to use `default`.  Nobody is talking about forcing you to use 
`unknown case`.  If you really dislike it you could even ban it with a linter.

> Dave

swift-evolution mailing list

Reply via email to