<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On 3. Jan 2018, at 18:49, Dave DeLong via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class="Apple-interchange-newline"><br class=""><blockquote type="cite" class=""><div class="">On Jan 3, 2018, at 10:36 AM, Matthew Johnson <<a href="mailto:matthew@anandabits.com" class="">matthew@anandabits.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Jan 3, 2018, at 11:07 AM, Dave DeLong via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">IMO this is still too large of a hammer for this problem.<div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">What feels far more appropriate is:</div><div class=""><br class=""></div><div class="">🅰️ 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.</div></div></div></blockquote><div class=""><br class=""></div><div class="">John McCall sketched out a vision of what a solution to this might look like here: <a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171218/042333.html" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171218/042333.html</a>. </div></div></div></div></blockquote><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div class=""><br class=""></div><div class="">and</div><div class=""><br class=""></div><div class="">🅱️ 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:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>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. </div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>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.</div></div></div></blockquote><div class=""><br class=""></div><div class="">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: <a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170904/039512.html" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170904/039512.html</a> 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.</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">Dave</div></div><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">_______________________________________________</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">swift-evolution mailing list</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="mailto:swift-evolution@swift.org" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">swift-evolution@swift.org</a><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote><br class=""></div><div>So here’s something that I’m confused about - you said before that when the library updates, the application behaviour should remain the same. Then why is it up to the App developers to try and develop forwards-compatible logic instead of the library developers to ensure backwards-compatibility?</div><div><br class=""></div><div>SKPaymentTransactionState is a great example - it’s exactly what this proposal is about. We are all looking at the superficial side of keeping App code compiling, when really we should be thinking about the semantics that those enums represent. Enums usually mean state, and it’s often difficult to design good state-machines which can deal with completely unpredictable values popping up. Most of the the time, your default handler is just garbage which you expect and hope never gets called IRL.</div><div><br class=""></div><div>I’m not convinced that it is possible to write a good default handler for SKPaymentTransactionState, or really most enums. If there were other properties you could inspect to perform your App logic, you should clearly prefer those since they are more robust than an enum which may give you unpredictable values in the future. How would users even know about this recommended practice of ignoring the enum and looking for ad-hoc state properties? Again, getting this stuff right requires careful design and documentation from the library developers, regardless if enums are exhaustive or not.</div><div><br class=""></div><div>I think the StoreKit library authors got it wrong there; they added a new enum case which required special handling; that’s an API-breaking change. They should have defined backwards-compatibility behaviour (if that was possible), or disabled the feature for Apps which didn’t support it. Just throwing out values which you know the App doesn’t understand puts you in dangerous territory, even if it doesn’t necessarily crash.</div><div><br class=""></div><div>- Karl</div><div><br class=""></div></body></html>