<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 Sep 22, 2017, at 17:50, Rex Fenley <<a href="mailto:rex@remind101.com" class="">rex@remind101.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">It’s really only an issue for people whose frameworks are used across variously-distributed apps (your own, or other peoples’). The typical dynamic library use-case. Those people already know to be careful, so why make non-exhaustive the default for everybody? It’s a fair point.<br class=""></blockquote><div class=""> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">Getting this right can be pretty hard. For example, I expect that @_inlineable functions within the enum’s declaring module will also be affected by this (a client could inline the code, then you add an enum case…). At the same time, it’s difficult for a shared library vendor to say definitively that a particular enum will never change (unless it really is a very simple thing, like NSComparisonResult) - almost anything with meaning to how the library works is usually subject to change in case edge-cases are discovered. The analysis of Apple’s frameworks is good data to prove it, but it also makes sense that vendors like to retain as much implementation freedom as possible.</blockquote><div class=""><br class=""></div><div class="">Just for clarity, this seems like the binary compatibility piece correct? As far as I understand this could only affect a dynamically linked library, but if you're linking a library dynamically, how could you inline a function, since if it's dynamically linked you don't know what to inline?</div><div class=""></div></div></div></blockquote><div><br class=""></div><div>Karl answered this part already, but this is equivalent to `static inline` functions in C. The library is dynamically linked, but specific pieces of it are available for clients to inline.</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="">Also, I've never heard of these kinds of issues in other languages with exhaustive pattern matching. Would be very interested to know how OCaml or Haskell solve this problem?</div></div></div></blockquote><br class=""></div><div>This is a great question, and I feel a little ashamed that I didn't include a proper cross-language study ahead of time!</div><div><br class=""></div><div>As far as I can tell, <b class="">Haskell</b> and <b class="">OCaml</b> completely punt on this issue. All "enums" are exhaustive (the existing Swift behavior), and adding a new "case" to a "public enum" is a source-breaking change all the time. (Neither Haskell nor OCaml seems to care much about binary compatibility.) This is definitely a sign that you can have a successful language without a form of non-exhaustive enums other than "protocols". However, I think that just means that people never add new cases to existing enums, which is not where we want to end up with Swift. <b class="">Kotlin</b> also falls in this bucket.</div><div><br class=""></div><div><b class="">Scala</b>'s notion of enums is "sealed traits", which is something like a protocol that can only be conformed to from a particular file. The compiler then checks for all the possible types and allows you to exhaustively switch over them. In some sense that means Scala is matching our behavior, in that they're "non-exhaustive by default, exhaustive via 'sealed'", but doing that with protocols isn't really equivalent because in the non-sealed case someone could conform to the protocol from <i class="">outside</i> the "module".</div><div><br class=""></div><div><b class="">Rust</b> has an accepted proposal to add <a href="https://github.com/rust-lang/rfcs/blob/master/text/2008-non-exhaustive.md" class="">non-exhaustive enums</a> that looks a lot like this one, but where "exhaustive" is still the default to not break existing Rust programs. (There are some interesting differences that come up in Rust but not Swift; in particular they need a notion of non-exhaustive <i class="">structs</i> because their structs can be decomposed in pattern-matching as well.)</div><div><br class=""></div><div>There's a <b class="">C++</b> proposal about an <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0375r0.html" class="">[[exhaustive]] attribute</a> that roughly matches this use case, although of course in C "falling off the end of a switch" is perfectly legal. The proposed attribute would merely be a hint to compilers for what warnings to emit.</div><div><br class=""></div><div>Enums in <b class="">D</b> are like enums in C, but D distinguishes `switch` from `final switch`, and only the latter is exhaustive. (That is, it's a client-side decision.)</div><div><br class=""></div><div><b class="">F#</b> unions <a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/signatures" class="">either expose all of their "cases" or none of them</a>. I guess the Swift equivalent of this would be not allowing you to switch on such an enum at all, as if it were a struct with private fields.</div><div><br class=""></div><div>The <b class="">C# </b>docs have a nice section on <a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/enum#robust-programming" class="">how the language isn't very helpful</a> for non-exhaustive enums. Objective-C, of course, is in the same bucket, though we (Apple) could start doing things with the 'enum_extensibility' attribute we just added.</div><div><br class=""></div><div>---</div><div><br class=""></div><div>I'm not sure this'll change anyone's mind, but it was still a good exercise. I'll add this to the proposal as well, so people don't have to dig through the thread to find this information.</div><div><br class=""></div><div>Jordan</div><br class=""></body></html>