default branch placement in switch

Brian Goetz brian.goetz at oracle.com
Thu Dec 14 20:08:05 UTC 2017


That would also be OK, as the two different versions of the rule are not 
very far apart in practice -- nearly all switches that will take a 
broader argument type will also want to do something more interesting 
with it (type test, deconstruct, etc.)


On 12/14/2017 2:42 PM, Guy Steele wrote:
> I think this is the right approach.
>
> An alternative that should at least be considered would be to further 
> simplify the statement of the exception by eliminating the mention of 
> legacy types:
>
>  - For switches which have only constant case labels (and "default"), 
> we relax the above rule regarding default.
>
>
>> On Dec 14, 2017, at 2:39 PM, Brian Goetz <brian.goetz at oracle.com 
>> <mailto:brian.goetz at oracle.com>> wrote:
>>
>> Here's where I think we should come down on this.
>>
>> First, we should appeal to the general rule about pattern ordering; 
>> if pattern X dominates Y (that is, everything that matches Y also 
>> matches X), X can't come before Y.
>>
>> This gives us:
>>  - "case null" must precede any non-constant case label
>>  - "default" must come at the end.
>>
>> Now, we carve out special dispensation for existing switches:
>>  - For switches whose static argument type is one of the legacy 
>> switch types (primitives, boxes, string, enum) *and* which have only 
>> constant case labels (and "default"), we relax the above rule 
>> regarding default.
>>
>>
>>
>> On 12/11/2017 2:15 PM, Brian Goetz wrote:
>>> The middle is surely awful.  Though in the JDK, we have a fair 
>>> number of uses where default is the _first_ case, which isn't 
>>> unreasonable, and some might argue is even clearer in some cases.
>>>
>>> The reason to tread lightly on forcing reorganization of existing 
>>> switches is that it is allowable to fall into *and out of* the 
>>> default case.  So if someone has:
>>>
>>>     switch (x) {
>>>         default:  S;   // fall through
>>>         case COMMON: T; break;
>>>         case UNCOMMON: U; break;
>>>     }
>>>
>>> then eventually getting to an error when default is not last for 
>>> "legacy" switches (those where all labels are type-restating 
>>> constants) means some uncomfortable refactoring just to "make the 
>>> compiler happy."  So while I agree on warnings, I'm not sure if we 
>>> can ever get to error in all cases without picking some fights with 
>>> users.
>>>
>>>
>>>
>>> On 12/11/2017 1:16 PM, Kevin Bourrillion wrote:
>>>> On Fri, Nov 3, 2017 at 5:25 PM, Brian Goetz <brian.goetz at oracle.com 
>>>> <mailto:brian.goetz at oracle.com>> wrote:
>>>>
>>>>
>>>>     or plan to eventually get to a place where default always comes
>>>>     last, even for "int" switches. If we want to get to the latter,
>>>>     we should start warning on this construct now.
>>>>
>>>>
>>>> I favor starting to warn and eventually forbidding default in any 
>>>> position but last for all constructs that have it.
>>>>
>>>> A switch with the default in the middle is extremely weird and 
>>>> confusing. If I'm reading code to understand what happens when i == 
>>>> 3, and I read as far as
>>>>
>>>>     switch (i) {
>>>>       case 1:
>>>>         justOneStuff(); break();
>>>>       case 2:
>>>>         justTwoStuff(); break();
>>>>       default:
>>>>
>>>> ... then I immediately assume that this must be where execution is 
>>>> continuing. Worse, even if I do notice that there are more case 
>>>> labels to follow, and I resume searching for a `case 3:`, then when 
>>>> I don't find one I now risk making /another/ error and forgetting 
>>>> to jump /back/ to the default.
>>>>
>>>> This is kind of insane. At first I was less worried because I 
>>>> thought "surely no one is actually doing this"... then I browsed 
>>>> our codebase.... yikes.
>>>>
>>>> We should at least strongly consider this.
>>>>
>>>>
>>>>
>>>>     On 11/3/2017 5:10 PM, Tagir Valeev wrote:
>>>>
>>>>         Hello!
>>>>
>>>>         Currently the default branch can be placed in any place
>>>>         inside the
>>>>         switch operator, e.g. like this:
>>>>
>>>>         switch(i) {
>>>>         case 1: System.out.println("one");break;
>>>>         default: System.out.println("other");break;
>>>>         case 2: System.out.println("two");break;
>>>>         }
>>>>
>>>>         In this case behavior does not change on the order of case
>>>>         blocks.
>>>>         However in pattern matching the order of cases usually
>>>>         matters: if
>>>>         some pattern matches, this means that the subsequent
>>>>         patterns will not
>>>>         be checked. Does this mean that with pattern matching the
>>>>         default
>>>>         branch makes all the subsequent case blocks unreachable? Or
>>>>         default
>>>>         can still be located anywhere and is checked only after any
>>>>         other
>>>>         pattern?
>>>>
>>>>         With best regards,
>>>>         Tagir Valeev
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> -- 
>>>> Kevin Bourrillion | Java Librarian | Google, 
>>>> Inc. |kevinb at google.com <mailto:kevinb at google.com>
>>>
>>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20171214/df0f4b06/attachment.html>


More information about the amber-spec-experts mailing list