Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8339296

Record deconstruction pattern in switch fails to compile

XMLWordPrintable

    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      openjdk version "22.0.2" 2024-07-16
      OpenJDK Runtime Environment Zulu22.32+15-CA (build 22.0.2+9)
      OpenJDK 64-Bit Server VM Zulu22.32+15-CA (build 22.0.2+9, mixed mode, sharing)

      Mac OS 14.5 (23F79)

      A DESCRIPTION OF THE PROBLEM :
      The following code fails to compile with an unexpected crash report. I wrote several comments in the code sample to show how I narrowed down the problem.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile the code sample with "javac Test.java"

      ACTUAL -
      An exception has occurred in the compiler (22.0.2). 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 invoke "com.sun.tools.javac.code.Type.isErroneous()" because "record.type" is null
      at jdk.compiler/com.sun.tools.javac.comp.Flow.makePatternDescription(Flow.java:3471)
      at jdk.compiler/com.sun.tools.javac.comp.Flow$AliveAnalyzer.exhausts(Flow.java:780)
      at jdk.compiler/com.sun.tools.javac.comp.Flow$AliveAnalyzer.visitSwitchExpression(Flow.java:762)
      at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCSwitchExpression.accept(JCTree.java:1399)
      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$AliveAnalyzer.visitYield(Flow.java:1205)
      at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCYield.accept(JCTree.java:1677)
      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.tree.TreeScanner.scan(TreeScanner.java:58)
      at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.visitCase(TreeScanner.java:183)
      at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCCase.accept(JCTree.java:1343)
      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$AliveAnalyzer.analyzeTree(Flow.java:1276)
      at jdk.compiler/com.sun.tools.javac.comp.Flow.aliveAfter(Flow.java:284)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.handleSwitch(Attr.java:1858)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.visitSwitchExpression(Attr.java:1630)
      at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCSwitchExpression.accept(JCTree.java:1399)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:662)
      at jdk.compiler/com.sun.tools.javac.comp.DeferredAttr.attribSpeculative(DeferredAttr.java:515)
      at jdk.compiler/com.sun.tools.javac.comp.DeferredAttr.attribSpeculative(DeferredAttr.java:495)
      at jdk.compiler/com.sun.tools.javac.comp.DeferredAttr.attribSpeculative(DeferredAttr.java:466)
      at jdk.compiler/com.sun.tools.javac.comp.ArgumentAttr.lambda$processArg$0(ArgumentAttr.java:221)
      at jdk.compiler/com.sun.tools.javac.comp.ArgumentAttr.processArg(ArgumentAttr.java:243)
      at jdk.compiler/com.sun.tools.javac.comp.ArgumentAttr.processArg(ArgumentAttr.java:220)
      at jdk.compiler/com.sun.tools.javac.comp.ArgumentAttr.visitSwitchExpression(ArgumentAttr.java:261)
      at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCSwitchExpression.accept(JCTree.java:1399)
      at jdk.compiler/com.sun.tools.javac.comp.ArgumentAttr.attribArg(ArgumentAttr.java:198)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:660)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribArgs(Attr.java:763)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.visitApply(Attr.java:2603)
      at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1816)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:662)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.visitReturn(Attr.java:2476)
      at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCReturn.accept(JCTree.java:1728)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:662)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribStat(Attr.java:736)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribStats(Attr.java:755)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.visitBlock(Attr.java:1440)
      at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:1092)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:662)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribStat(Attr.java:736)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.visitMethodDef(Attr.java:1229)
      at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:916)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:662)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribStat(Attr.java:736)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribClassBody(Attr.java:5615)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribClass(Attr.java:5503)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribClass(Attr.java:5327)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attrib(Attr.java:5266)
      at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.attribute(JavaCompiler.java:1366)
      at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:976)
      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)

      ---------- BEGIN SOURCE ----------
      public class Test {
          sealed interface I permits R, C {}

          record R(String s) implements I {}

          static final class C implements I {}

          String method() {
              I i1 = null;
              I i2 = null;

              // DOES COMPILE
              // using the 'm' method, and a single switch
              //return m(switch (i2) {
              // case R(String s2) -> "";
              // case C c -> "";
              //});

              // DOES COMPILE
              // using nested switches but no 'm' method
              //return switch (i1) {
              // case R(String s1) -> switch (i2) {
              // case R(String s2) -> "";
              // case C c -> "";
              // };
              // case C c -> "";
              //};

              // DOESN'T COMPILE
              // Using both 'm' method and nested switches
              return m(switch (i1) {
                  case R(String s1) -> switch (i2) {
                      case R(String s2) -> ""; // It's related to this deconstructed record pattern. The compilation works with case R r -> ""
                      case C c -> "";
                  };
                  case C c -> "";
              });
          }

          String m(int i) {
              return "";
          }

          String m(String s) {
              return "";
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      As I mentionned in the code comments, the workaround is to not use record deconstruction pattern

      FREQUENCY : always


            jlahoda Jan Lahoda
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: