[swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

Jordan Rose jordan_rose at apple.com
Fri Jan 5 17:17:56 CST 2018



> On Jan 5, 2018, at 00:11, Jonathan Hull via swift-evolution <swift-evolution at swift.org> wrote:
> 
>> 
>> On Jan 4, 2018, at 11:02 PM, Xiaodi Wu <xiaodi.wu at gmail.com <mailto:xiaodi.wu at gmail.com>> wrote:
>> 
>> 
>> On Fri, Jan 5, 2018 at 01:56 Jonathan Hull <jhull at gbis.com <mailto:jhull at gbis.com>> wrote:
>>> On Jan 4, 2018, at 10:31 PM, Xiaodi Wu via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>>> 
>>> On Fri, Jan 5, 2018 at 00:21 Cheyo Jimenez <cheyo at masters3d.com <mailto:cheyo at masters3d.com>> wrote:
>> 
>>> 
>>> On Jan 4, 2018, at 4:37 PM, Xiaodi Wu <xiaodi.wu at gmail.com <mailto:xiaodi.wu at gmail.com>> wrote:
>>> 
>> 
>>>> On Thu, Jan 4, 2018 at 19:29 Cheyo J. Jimenez <cheyo at masters3d.com <mailto:cheyo at masters3d.com>> wrote:
>>>> 
>>>> We seem to agree that, by virtue of not supporting use in a pattern and being placed at the end, the feature is a flavor of default. I’m still not sure I understand why you believe it should not be a flavor of default going forward.
>>>> 
>>>>> 
>>>>> You still haven’t answered my question, though—what’s the use case for the feature you propose?
>>>> 
>>>> My use case would be distinguishing between compile time known cases vs “future only” cases (or unknown cases).
>>>> 
>>>> I understand that the feature you propose would allow you to make such a distinction, but again, what is your use case for doing so?
>> 
>>> Breaking out early by checking unknown cases first. I admit this is not deal breaker, just a different style I’d like to see supported in the future. 
>> 
>>> 
>>> I'm still not sure I understand. How can the machine know that it's dealing with an unknown case without first checking if it matches any known case?
>> 
>> 
>> I had the same thought as Cheyo.  It isn’t a deal breaker… I like the compromise, but I would prefer it trigger only on an actual unknown case (as opposed to acting like default). I like to break failure cases out at the top when possible. I don’t see any good reason not to support that style.
>> 
>> To answer your question, in the naive sense, it basically is the same question as asking if it is a known case (and then taking the inverse). That doesn’t mean actually checking each case separately though. For example, if the enum cases are internally represented as an unsigned integer, and they are all together in a block, the compiler could simply check that it is greater than the max known value. You could probably even do a bit mask comparison in some cases...
>> 
>> These are obvious optimizations, but why does this require new syntax?
> 
> I am not sure I understand what you are asking. There isn’t additional syntax.  We are just arguing over the name + behavior of ‘unexpected:’.  You want it to behave like ‘default’ and I am saying that stops the use case I mention above.
> 
> 
>> What do you gain from writing the unknown case first?
> I know where to look for the failure cases.  I also tend put a bunch of guard statements near the beginning of a function.  It is just a programming style.
> 
> With my behavior of ‘unexpected:’ you can put it wherever you want.  Why limit that by forcing it to go at the end?
> 
>> Isn't this basically the same thing as asking for the ability to write the default case first, a frequently suggested and rejected syntax addition?
> 
> No.  I don’t think I have ever heard that asked for, but putting default in a different place has a different meaning.  The way I read a switch statement anyway is that it tries each case until it find one that matches.  Default matches everything, so it has to go at the end (since it will always match and nothing afterwards will be tried).
> 
> Having ‘unexpected:’ also match known/expected cases is problematic as a mental model.  I think that is just an artifact of the original proposal using default.  There is no reason 'unexpected:’ should have to handle known cases as well… let’s just have it trigger on unexpected ones.

I'm going to repeat this from my reply to Cheyo earlier: I really, really don't want recompiling code against a different version of the library to pick a different case than it did before.

(This might be a weak argument since overload resolution, protocol conformance checking, etc can end up picking a different declaration than it did before. But I would hope that the overloads or alternate protocol witnesses at least "do the same thing" in normal situations, if possibly more efficiently. I wouldn't expect that for `unknown case` vs. `default` if you actually had both of them.)


The reason `unknown case` has to match known cases is, again, for source compatibility. If the compiler only produces a warning, rather than an error, when you're missing a case, it has to do something if that case comes up. The most reasonable thing for it to do (in the absence of a separate `default`) is for that to go to the `unknown case`, just like it would have with the last version of the app. That's why I chose to associate it with `default` in the proposal, not the other way around.

Jordan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20180105/b00474a5/attachment.html>


More information about the swift-evolution mailing list