Compiler could be smarter when dealing with exhaustive switch and final variables?
Remi Forax
forax at univ-mlv.fr
Sat Oct 8 10:22:45 UTC 2022
> From: "David Alayachew" <davidalayachew at gmail.com>
> To: "amber-dev" <amber-dev at openjdk.org>
> Sent: Saturday, October 8, 2022 9:07:31 AM
> Subject: Compiler could be smarter when dealing with exhaustive switch and final
> variables?
> Hello Amber Dev Team,
> When if/else statements and final variables combine, the compiler can make some
> helpful assertions. Consider the following code.
> sealed interface SomeInterface {}
> record First() implements SomeInterface {}
> record Second() implements SomeInterface {}
> private void exhaustiveIfWithFinalUninitialized()
> {
> SomeInterface abc = new First();
> final int numA;
> final int numB;
> if (abc instanceof First)
> {
> numA = -1;
> numB = -1;
> }
> else if (abc instanceof Second)
> {
> numA = -2;
> numB = -2;
> }
> else
> {
> throw new IllegalStateException("This shouldn't be possible!");
> }
> System.out.println(numA + "");
> System.out.println(numB + "");
> }
> The above code compiles with no errors whatsoever. The compiler is smart enough
> to realize that, no matter what, numA and numB will most certainly be populated
> by the time we reach the print statements below the if statements.
> However, the compiler does not make the same realization when working with
> exhaustive switches. But since the switch statement is exhaustive, shouldn't
> the compiler be able to make the same realization here? If anything, the switch
> should be capable of all of the above and more, correct?
> private void exhaustiveSwitchWithFinalUninitialized()
> {
> final int numA;
> final int numB;
> SomeInterface abc = new First();
> switch (abc) //compiler error unless we uncomment the default
> {
> case First f ->
> {
> numA = 1;
> numB = 0;
> }
> case Second s ->
> {
> numA = 0;
> numB = 1;
> }
> /*
> default ->
> {
> numA = 2;
> numB = 2;
> }
> */
> }
> System.out.println(numA + "");
> System.out.println(numB + "");
> }
> I would like it if the compiler could make the same realizations it did for the
> if statement. I should also add, this seems to apply to all forms of exhaustive
> switch except for those with default clauses.
Hi David,
i think this is similar to
[ https://bugs.openjdk.org/browse/JDK-8294670 | https://bugs.openjdk.org/browse/JDK-8294670 ]
that i've reported recently.
> Obviously, this is easy to work around - I could just make a switch expression
> for each variable, and then just populate them individually. Alternatively, I
> could just put a default clause any time I need that compiler realization,
> though I give up some benefits from exhaustive switch as a result.
As a workaround, you can also group the values into a record (that can be local to the method) and use an expression switch and initialize the local variable after the switch.
You can even abuse of the switch + record pattern to extract numA and numB :)
record Pair(int numA, int numB) {}
switch(switch(abc) {
case First -> new Pair(1, 0);
case Second -> new Pair(0, 1);
}) {
case Pair(int numA, int numB) -> {
System.out.println(numA);
System.out.println(numB);
}
}
BTW, this kind of code is less unreadable in languages like Scala where the switch is postfix to the value switched upon and not prefix.
> Thank you all for your time and help!
> David Alayachew
regards,
Rémi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20221008/2e3b8228/attachment.htm>
More information about the amber-dev
mailing list