We have two not-great choices here:

 - Treat otherwise-boring switches on long/float/double/boolean (and their boxes) as legacy primitive switches, omitting the enhanced exhaustiveness checking;  - Treat switching on float/double/boolean and their boxes as triggering the enhanced exhaustiveness checking.

It is unfortunate that we have to have a carve-out for "old" switches, because this means an irregular and possibly-surprising boundary in the language, which users will have to learn (sometimes learning the hard way.)  But we do, and we accepted it as the cost of turbo-charging switch (new selector types, new case labels, better exhaustiveness, guards, null support, etc.)  Ideally we will have a path to gently guiding users away from the legacy behavior to the point where we are eventually comfortable promoting some warnings to errors, and this issue goes away, but that will surely take a long time, and I won't dwell on it here.

In the meantime, we have a choice of "which of these two irregular boundaries do we want the user to reason about":

 - A statement switch is exempt from exhaustiveness checking if it does not use patterns, null cases, guards, or switch on anything other than {byte,char,short,int}, their boxes, enums, or strings, or

 - A statement switch is exempt from exhaustiveness checking if it does not use patterns, null cases, guards, or switch on anything other than a primitive, their boxes, enums, or strings.

Remi makes the argument for the first path, on the basis of "let's freeze the legacy behavior to the legacy rules." This is a reasonable argument.  However, the opposite argument is also reasonable; that "typical user intuition" about "old switch" is closer to "primitives, boxes, enums, and strings", and that allowing the remaining primitive types to fit into the old model may minimize cognitive load on the user.  (It is easier to keep track of "primitives" than "the primitives that we thought were reasonable to switch over in 1995", since that set is kind of arbitrarily chosen.)

So while I don't have an answer, I do think that both possible answers have merit :)




On 10/25/2023 4:50 AM, Remi Forax wrote:


------------------------------------------------------------------------

    *From: *"Angelos Bimpoudis" <[email protected]>
    *To: *"amber-spec-experts" <[email protected]>
    *Cc: *"Yuriy Maslyanko" <[email protected]>
    *Sent: *Wednesday, October 25, 2023 12:49:18 AM
    *Subject: *Fw: JEP 455: Non-enhanced switch statements

    Hello all!


Hello Angelos,


    Yuriy pointed out a valid point.

    1) Should we treat float/double/boolean/longs as a new addition to
    the non-enhanced switch (old switch) and support anything new that
    comes with that?

    or

    2) Should we treat those data types equally with all the
    pre-existing ones?

    I am strongly in favour of the 2) for the shake of symmetry and
    uniformity in what the user will assume, thus I will fix the bug.

    What do others think?


We have already discuss that, when we have introduce the switch on objects. The question is not what our current users will assume now but how the whole semantics of switch will be see let say 5 years from now, when people are used to use the switch on objects. The old switch is not a feature used a lot, we expected the new switch on objects to be used a lot more, so at some points, most of the switches will be switches on object so the semantics of the old switch will be the outlier. So the switch on float/double should behave like on objects, i.e. be hexaustive by default. It's the same reason why adding a "case null" or a "where" condition transforms the switch to the new semantics.

And there is another reason to make the switch on float/double exhaustive, the matching of a cases on primitive types can be partial, when we discussed that feature this is was obvious for some of us (me included). By making the switch exhaustive, we actually help users to understand the actual semantics, because the compiler will requires a "default" if the pattern matching is not total.

regards,
Rémi


    ------------------------------------------------------------------------
    *From:* Yuriy Maslyanko <[email protected]>
    *Sent:* 24 October 2023 21:57
    *To:* Angelos Bimpoudis <[email protected]>
    *Cc:* [email protected] <[email protected]>
    *Subject:* JEP 455: Non-enhanced switch statements

    Hi Angelos,

    Section 14.11.2 of
    
https://cr.openjdk.org/~abimpoudis/instanceof/jep443-20231010/specs/instanceof-jls.html#jls-14.11.2
    
<https://cr.openjdk.org/~abimpoudis/instanceof/jep443-20231010/specs/instanceof-jls.html#jls-14.11.2>
    has this note:

    For compatibility reasons, |switch| statements that are not
    enhanced |switch| statements are not required to be exhaustive.

    Noticed that if the switch selector statement is
    float/double/boolean (in this case it’s a non-enhanced switch
    statement), the code shown below fails with “error: the switch
    statement does not cover all possible input values”:

        static boolean check = false;

        public static boolean testMethod() {

            double v1 = 1d;

            switch ( v1 ) {

                case 1d:

                    check = true;

                    break;

            }

            return check;

        }



Reply via email to