<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><br><div>On Sep 29, 2017, at 18:21, Jordan Rose via swift-dev <<a href="mailto:swift-dev@swift.org">swift-dev@swift.org</a>> wrote:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html; charset=utf-8">Hello again, swift-dev! This is a sort of follow-up to "What can you change in a fixed-contents struct" from a few weeks ago, but this time concerning enums. Worryingly, this seems to be an important consideration even for non-exhaustive enums, which are normally the ones where we'd want to allow a developer to do anything and everything that doesn't break source compatibility.<div class=""><br class=""></div><div class="">[<b class="">This only affects libraries with binary compatibility concerns</b>. Libraries distributed with an app can always allow the app to access the enum's representation directly. That makes this an Apple-centric problem in the near term.]<br class=""><div class=""><br class=""></div><div class="">So, what's the issue? <b class="">We want to make it efficient to switch over a non-exhaustive enum</b>, even from a client library that doesn't have access to the enum's guts. We do this by asking for the enum's tag separately from its payload (pseudocode):</div></div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">switch getMyOpaqueEnumTag(&myOpaqueEnum) {</div><div class="">case 0:</div><div class=""> var payload: Int</div><div class=""> getMyOpaqueEnumPayload(&myOpaqueEnum, 0, &payload)</div><div class=""> doSomething(payload)</div><div class="">case 1:</div><div class=""> var payload: String</div><div class=""> getMyOpaqueEnumPayload(&myOpaqueEnum, 1, &payload)</div><div class=""> doSomethingElse(payload)</div><div class="">default:</div><div class=""> print("unknown case")</div><div class="">}</div></blockquote><br class=""><div class="">The tricky part is those constant values "0" and "1". We'd really like them to be constants so that the calling code can actually emit a jump table rather than a series of chained conditionals, but that means <b class="">case tags are part of the ABI, even for non-exhaustive enums</b>.</div><div class=""><br class=""></div><div class="">Like with struct layout, this means we need a stable ordering for cases. Since non-exhaustive enums can have new cases added at any time, we can't do a simple alphabetical sort, nor can we do some kind of ordering on the payload types. The naive answer, then, is that <b class="">enum cases cannot be reordered, even in non-exhaustive enums</b>. This isn't great, because people like being able to move deprecated enum cases to the end of the list, where they're out of the way, but it's at least explainable, and consistent with the idea of enums some day having a 'cases' property that includes all cases.</div><div class=""><br class=""></div><div class="">Slava and I aren't happy with this, but we haven't thought of another solution yet.</div></div></blockquote><div><br></div>If this is only an issue for things with “binary compatibility concerns”, could we pass the old (well, “current release”) version of the binary to the compiler and have it extract the ordering info from that? I mean it seems like a reasonable assumption that a vendor would have access to what would be the current version of their product.<div><div><br></div><div>- Dave Sweeris</div></div></body></html>