<html><body><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000"><div><br></div><div><br></div><hr id="zwchr" data-marker="__DIVIDER__"><div data-marker="__HEADERS__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From: </b>"David Alayachew" <davidalayachew@gmail.com><br><b>To: </b>"amber-dev" <amber-dev@openjdk.org><br><b>Sent: </b>Saturday, October 8, 2022 9:07:31 AM<br><b>Subject: </b>Compiler could be smarter when dealing with exhaustive switch and final variables?<br></blockquote></div><div data-marker="__QUOTED_TEXT__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="ltr"><div class="gmail_default" style="font-family:monospace">Hello Amber Dev Team,</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">When if/else statements and final variables combine, the compiler can make some helpful assertions. Consider the following code.<br></div><div style="font-family:monospace" class="gmail_default"> <br> sealed interface SomeInterface {}<br> record First() implements SomeInterface {}<br> record Second() implements SomeInterface {} <br> <br> private void exhaustiveIfWithFinalUninitialized()<br> {<br> <br> SomeInterface abc = new First();<br> <br> final int numA;<br> final int numB;<br> <br> if (abc instanceof First)<br> {<br> <br> numA = -1;<br> numB = -1;<br> <br> }<br> <br> else if (abc instanceof Second)<br> {<br> <br> numA = -2;<br> numB = -2;<br> <br> }<br> <br> else<br> {<br> <br> throw new IllegalStateException("This shouldn't be possible!");<br> <br> }<br> <br> System.out.println(numA + "");<br> System.out.println(numB + "");<br> <br> }</div><div style="font-family:monospace" class="gmail_default"><br></div><div class="gmail_default" style="font-family:monospace">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. <br></div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">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? <br></div><div class="gmail_default" style="font-family:monospace"> <br> private void exhaustiveSwitchWithFinalUninitialized()<br> {<br> <br> final int numA;<br> final int numB;<br> <br> SomeInterface abc = new First();<br> <br> switch (abc)
//compiler error unless we uncomment the default
<br> {<br> <br> case First f -><br> {<br> <br> numA = 1;<br> numB = 0;<br> <br> }<br> <br> case Second s -> <br> {<br> <br> numA = 0;<br> numB = 1;<br> <br> }<br> /*<br> default -><br> {<br> <br> numA = 2;<br> numB = 2;<br> <br> }<br> */<br> }<br> <br> System.out.println(numA + "");<br> System.out.println(numB + "");<br> <br> }</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">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.</div></div></blockquote><div><br></div><div><div>Hi David,</div><div>i think this is similar to</div><div> <a href="https://bugs.openjdk.org/browse/JDK-8294670" data-mce-href="https://bugs.openjdk.org/browse/JDK-8294670">https://bugs.openjdk.org/browse/JDK-8294670</a><br data-mce-bogus="1"></div><div>that i've reported recently.</div></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="ltr"><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">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.<br></div></div></blockquote><div><br></div>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.</div><div data-marker="__QUOTED_TEXT__"><br data-mce-bogus="1"></div><div data-marker="__QUOTED_TEXT__">You can even abuse of the switch + record pattern to extract numA and numB :)<br></div><div data-marker="__QUOTED_TEXT__"><br data-mce-bogus="1"></div><div data-marker="__QUOTED_TEXT__"> record Pair(int numA, int numB) {}</div><div data-marker="__QUOTED_TEXT__"> switch(switch(abc) {<div data-marker="__QUOTED_TEXT__"> case First -> new Pair(1, 0);<br> case Second -> new Pair(0, 1);</div><div data-marker="__QUOTED_TEXT__"> }) {<br data-mce-bogus="1"></div></div><div data-marker="__QUOTED_TEXT__"> case Pair(int numA, int numB) -> {<br data-mce-bogus="1"></div><div data-marker="__QUOTED_TEXT__"> System.out.println(numA);<br data-mce-bogus="1"></div><div data-marker="__QUOTED_TEXT__"> System.out.println(numB);<br data-mce-bogus="1"></div><div data-marker="__QUOTED_TEXT__"> }<br data-mce-bogus="1"></div><div data-marker="__QUOTED_TEXT__"> }</div><div data-marker="__QUOTED_TEXT__"><div><br data-mce-bogus="1"></div><div>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.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="ltr"><div class="gmail_default" style="font-family:monospace">Thank you all for your time and help!</div><div class="gmail_default" style="font-family:monospace">David Alayachew</div></div></blockquote><div><br></div><div>regards,<br data-mce-bogus="1"></div><div>RĂ©mi<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div></div></div></body></html>