<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 7, 2017, at 1:45 PM, Robert Widmann via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">I lean +1, but this answer on its own seems incomplete. &nbsp;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. &nbsp;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 <span style="color: rgb(186, 45, 162); font-family: Menlo; font-size: 11px;" class="">default</span>&nbsp;now covering the rest of the cases the compiler is unable to tell you which cases you are actually missing post-upgrade.<div class=""><br class=""></div><div class=""><a href="https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst" class="">Library Evolution</a>&nbsp;includes what I think is the more complete response here: An&nbsp;<span style="color: rgb(186, 45, 162); font-family: Menlo; font-size: 11px;" class="">@closed</span>&nbsp;attribute for enums where a switch is guaranteed to be exhaustive. &nbsp;(Though, after the <font color="#ba2da2" face="Menlo" class=""><span style="font-size: 11px;" class="">open&nbsp;</span></font>discussion, I wonder if that keyword can’t be reused in some way to provide the inverse restriction instead).<br class=""></div></div></div></blockquote><div><br class=""></div><div>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. &nbsp;</div><div><br class=""></div><div>Personally, if we have a default I would prefer for the default to be closed. &nbsp;One of the most important attributes of enums is the fact that they encompass a fixed set of known cases. &nbsp;I *want* my code to break if a new case is added to an enum of another module I depend on. &nbsp;As the Library Evolution document notes "adding new cases should not be done lightly. Any clients attempting to do an&nbsp;exhaustive switch over all enum cases will likely not handle new cases well.”. &nbsp;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.</div><div><br class=""></div><div>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. &nbsp;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.</div><div><br class=""></div><div>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. &nbsp;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. &nbsp;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”. &nbsp;That is basically equivalent to the meaning of `public` for classes.</div><div><br class=""></div><div>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. &nbsp;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.</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Feb 7, 2017, at 10:12 AM, Tanner Nelson via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">Hello Swift Evolution,<div class=""><br class=""></div><div class="">I'd like to propose that a warning be emitted when default cases are omitted for enums from other modules.&nbsp;</div><div class=""><br class=""></div><div class="">What this would look like:</div><div class=""><br class=""></div><div class="">OtherModule:</div><div class="">```</div><div class="">public enum SomeEnum {</div><div class="">&nbsp; &nbsp; case one</div><div class="">&nbsp; &nbsp; case two</div><div class="">}</div><div class=""><br class=""></div><div class="">public let global: SomeEnum = .one</div><div class="">```</div><div class=""><br class=""></div><div class="">executable:</div><div class="">```</div><div class="">import OtherModule</div><div class=""><br class=""></div><div class="">switch OtherModule.global {</div><div class="">&nbsp; &nbsp; case .one: break</div><div class="">&nbsp; &nbsp; case .two: break</div><div class="">&nbsp; &nbsp; ^~~~~ ⚠︎ Warning: Default case recommended for imported enums. Fix-it: Add `default: break`</div><div class="">}</div><div class="">```</div><div class=""><br class=""></div><div class="">Why:</div><div class=""><br class=""></div><div class="">Allowing the omission of a default case in an exhaustive switch makes the addition of a new case to the enum a breaking change.&nbsp;</div><div class="">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).</div><div class=""><br class=""></div><div class="">Background:</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">Related Twitter thread:&nbsp;<a href="https://twitter.com/tanner0101/status/796860273760104454" class="">https://twitter.com/tanner0101/status/796860273760104454</a></div><div class=""><br class=""></div><div class="">Looking forward to hearing your thoughts.</div><div class=""><br class=""></div><div class="">Best,</div><div class="">Tanner</div><div class=""><br class=""></div><div class=""><div style="font-family:'sf ui text';font-size:12px" class=""><font color="#5f5f5f" class="">Tanner Nelson</font></div><div style="font-family:'sf ui text';font-size:12px" class=""><font color="#9dacd1" class="">Va</font><font color="#aeb2cf" class="">p</font><font color="#c8bacd" class="">o</font><font color="#d0becc" class="">r</font><font color="#9dacd1" class="">&nbsp;</font></div><div style="font-family:'sf ui text';font-size:12px" class=""><font color="#676767" class="">+1 (435) 773-2831</font></div></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div></div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class=""></div></div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>