Why does an incomplete switch expression compile successfully
Asked Answered
G

1

10

Trying out JDK/12 EarlyAccess Build 20, where the JEP-325 Switch Expressions has been integrated as a preview feature. A sample code for the expressions (as in the JEP as well):

Scanner scanner = new Scanner(System.in);
Day day = Day.valueOf(scanner.next().toUpperCase());
int i = switch (day) {
    case MONDAY,TUESDAY, WEDNESDAY:
        break 0;
    default:
        System.out.println("Second half of the week");
        // ERROR! Group doesn't contain a break with value
};

I was trying to follow the same procedure as stated in a previous question on how to Compile a JDK12 preview feature with Maven and execute the above block of code using the command line:

java --enable-preview -jar target/jdk12-updates-1.0.0-SNAPSHOT.jar

Somewhat to my expectation I got the following error :

Error: Unable to initialize main class
com.stackoverflow.nullpointer.expression.SwitchExpressionMustComplete
Caused by: java.lang.VerifyError: Bad local variable type Exception
Details:   Location:
    com/stackoverflow/nullpointer/expression/SwitchExpressionMustComplete.main([Ljava/lang/String;)V @66: iload   
Reason:
    Type top (current frame, locals[4]) is not assignable to integer   
Current Frame:
    bci: @66
    flags: { }
    locals: { '[Ljava/lang/String;', 'java/util/Scanner', 'com/stackoverflow/nullpointer/Day' }
    stack: { }   
Bytecode:
    0000000: bb00 0259 b200 03b7 0004 4c2b b600 05b8
    0000010: 0006 4db2 0007 2cb6 0008 2eaa 0000 001f
    0000020: 0000 0001 0000 0003 0000 0019 0000 0019
    0000030: 0000 0019 0336 04a7 000b b200 0912 0ab6
    0000040: 000b 1504 3eb1                        
Stackmap Table:
    append_frame(@52,Object[#2],Object[#34])
    same_frame(@58)
    same_frame(@66)

I am aware that the document points out that the code is erroneous and replacing the comment with break 1; resolves it, but the questions I have are:

Q1. Why does the compile phase succeed for the same? Shouldn't that fail at compile time itself?

Q2. What is the cause that I see such detailed error message? Could the --enable-preview feature responsible for this?

Gattis answered 19/11, 2018 at 19:22 Comment(0)
P
10

This is a known bug. See JDK-8212982 for details on its status.

This code:

public class SwitchBug { 

    static String hold(String item) { 
        return switch(item) { 
            case String s -> { System.out.println(s); } 
            default -> "temp"; 
        }; 
    } 

    public static void main(String[] args) { 
        System.out.println(hold("bug")); 
    } 
}

compiles and produces:

bug 
temp 

This program should not compile, as the first case completes normally.

Portecochere answered 19/11, 2018 at 22:2 Comment(4)
Well, not sure how these are linked, but on the contrary the code in this bug report actually fails to compile for me with error : or -> expected .... not a statementGattis
How about the other part of the question, what is the reason that I see such detailed error message? (Not that I am worried about seeing it, just curious to know if I could use some JVM flag to toggle to this view for errors reported.)Gattis
@Gattis in the example of this answer, the erroneous case is before a value returning case, so the code flow reaches the subsequent case and executes it, wrongly returning that value. In your question’s example, there is no case behind the erroneous one, so it leaves the local variable uninitialized. But apparently your actual code contained an attempt to use that variable afterwards and having a code path that would use an uninitialized variable makes the bytecode invalid. So the code gets rejected by the JVM’s verifier and what you see is a VerifyError with HotSpot’s diagnostics.Tatiania
@Tatiania Indeed I was using the variable after the switch expression and good to know the reason why I got those detailed logs. Thanks for sharing the details.Gattis

© 2022 - 2024 — McMap. All rights reserved.