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>
>>>
>>
>
More information about the amber-spec-observers
mailing list