<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 3:01 PM, Michael Ilseman 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=""><div class="">BTW, this will likely be part of the eventual design of “open”/resilient enums ala&nbsp;<a href="https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums" class="">https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums</a>. There, the goal is to reduce both ABI and source breakage caused by this sort of thing. It seems like for your purposes, you’re less inclined to care about ABI breakage than source breakage, though that may change in the future.</div></div></div></blockquote><div><br class=""></div><div>Source breakage is generally *desirable* in the context of switch statements over the cases of an enum. &nbsp;This is why I am strongly opposed to the idea of making open enums the default. &nbsp;</div><div><br class=""></div><div>It feels like this would only be a desirable API contract for enums which it would be unusual for user code to switch over. &nbsp;Any time user code might reasonably switch over the cases it feels like the wrong API contract. &nbsp;How is the user code supposed to handle the unknown future cases correctly? &nbsp;</div><div><br class=""></div><div>I think it’s also worth asking the question: if user code is not supposed to switch over the cases of the enum, why is the type exposed publicly as an enum at all? &nbsp;This means the cases are only intended to be used by the user to create values of the type. &nbsp;Maybe a better API design would be something like the following:</div><div><br class=""></div><div>public&nbsp;struct&nbsp;Foo {<br class="">&nbsp; &nbsp;&nbsp;private&nbsp;enum&nbsp;Value {<br class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;case&nbsp;foo1<br class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;case&nbsp;foo2(String)<br class="">&nbsp; &nbsp;&nbsp;}<br class=""><br class="">&nbsp; &nbsp;&nbsp;private&nbsp;let&nbsp;value:&nbsp;Value<br class="">&nbsp; &nbsp;&nbsp;private&nbsp;init(_&nbsp;value:&nbsp;Value) {<br class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.value&nbsp;= value<br class="">&nbsp; &nbsp;&nbsp;}<br class=""><br class="">&nbsp; &nbsp;&nbsp;public&nbsp;static&nbsp;var&nbsp;foo1:&nbsp;Foo&nbsp;{<br class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;Foo(.foo1)<br class="">&nbsp; &nbsp;&nbsp;}<br class="">&nbsp; &nbsp;&nbsp;public&nbsp;static&nbsp;func&nbsp;foo2(_&nbsp;value:&nbsp;String) -&gt;&nbsp;Foo&nbsp;{<br class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;Foo(.foo2(value))<br class="">&nbsp; &nbsp;&nbsp;}<br class="">}<br class=""><br class="">public&nbsp;func&nbsp;apiFunctionTakingFoo(_&nbsp;foo:&nbsp;Foo) {}</div><div><br class=""></div><div>// user code:<br class="">apiFunctionTakingFoo(.foo1)<br class="">apiFunctionTakingFoo(.foo2(""))</div><div><br class=""></div><div>This provides the same syntactic convenience for users when constructing values and allows adding new values (i.e. “cases”), retains the ability to use an enum internally in the implementation, and intentionally prevents users from switching over the open set of values in a fragile way (i.e. handling unknown future values / cases in a `default` clause). &nbsp;</div><div><br class=""></div><div>This requires some boilerplate but it feels like it may often be a better API design when the library author is not willing to commit to the contract of a closed enum. &nbsp;It feels like it should be unusual when a library author expects users to switch over the cases, but also wants to add new cases in the future.</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=""><br class=""></div><div class=""><br class=""></div><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Feb 7, 2017, at 7: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>_______________________________________________<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>