RFR: 8331212: Error recovery for broken switch expressions could be improved

Jan Lahoda jlahoda at openjdk.org
Mon Apr 29 11:56:18 UTC 2024


Consider code like:

class Test {
    public boolean test() {
        return switch (0) {
            case 0 -> true;
            default -> {}
        };
    }
}


when compiling this, javac reports and error, and then crashes with an exception:

$ javac -XDdev /tmp/Test.java
/tmp/Test.java:5: error: switch rule completes without providing a value
            default -> {}
                        ^
  (switch rules in switch expressions must either provide a value or throw)
1 error
An exception has occurred in the compiler (23-internal). Please file a bug against the Java compiler via the Java bug reporting page (https://bugreport.java.com) after checking the Bug Database (https://bugs.java.com) for duplicates. Include your program, the following diagnostic, and the parameters passed to the Java compiler in your report. Thank you.
java.lang.NullPointerException: Cannot read field "type" because "tree" is null
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.scanCond(Flow.java:2363)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitYield(Flow.java:2990)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCYield.accept(JCTree.java:1673)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:50)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:463)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:2095)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scanSyntheticBreak(Flow.java:475)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.handleSwitch(Flow.java:2802)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitSwitchExpression(Flow.java:2777)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCSwitchExpression.accept(JCTree.java:1395)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:50)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:463)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:2095)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.scanExpr(Flow.java:2340)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitReturn(Flow.java:3023)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCReturn.accept(JCTree.java:1724)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:50)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:463)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:2095)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:58)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitBlock(Flow.java:2614)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:1088)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:50)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:463)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:2095)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitMethodDef(Flow.java:2517)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:912)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:50)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:463)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:2095)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitClassDef(Flow.java:2454)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:810)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:50)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:463)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:2095)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.analyzeTree(Flow.java:3251)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.analyzeTree(Flow.java:3233)
        at jdk.compiler/com.sun.tools.javac.comp.Flow.analyzeTree(Flow.java:231)
        at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1418)
        at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1392)
        at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:977)
        at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:319)
        at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:178)
        at jdk.compiler/com.sun.tools.javac.Main.compile(Main.java:66)
        at jdk.compiler/com.sun.tools.javac.Main.main(Main.java:52)
printing javac parameters to: .../javac.20240429_134610.args


This is because, at the end of a rule case (`case ->`), if the code in the case completes normally, `Flow` will visit a synthetic `yield` or `break`, to ensure `Flow` understands there is no fall through. But, for `yield`, there is no expression. This works in most cases, but not in a "condition" context (i.e. for type "boolean"), when the `null` is not silently ignored.

As this is error recovery, the proposed solution is to make sure the `yield` has an expression - an erroneous expression in this case.

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

Commit messages:
 - 8331212: Error recovery for broken switch expressions could be improved

Changes: https://git.openjdk.org/jdk/pull/18997/files
  Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=18997&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8331212
  Stats: 94 lines in 2 files changed: 93 ins; 0 del; 1 mod
  Patch: https://git.openjdk.org/jdk/pull/18997.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/18997/head:pull/18997

PR: https://git.openjdk.org/jdk/pull/18997


More information about the compiler-dev mailing list