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

Downcasting a two records returned from a nested switch to its common interface

XMLWordPrintable

    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      Windows 11, Java 19.01

      A DESCRIPTION OF THE PROBLEM :
      When using nested switch expressions and returning records which implements a sealed interface and casting the result form the outer switch explicitly, It throws an assertion error when compiling.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      javac -d ./out/ .\src\main\java\JFC.java

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Compiles
      ACTUAL -
      java.lang.AssertionError
              at jdk.compiler/com.sun.tools.javac.util.Assert.error(Assert.java:155)
              at jdk.compiler/com.sun.tools.javac.util.Assert.check(Assert.java:46)
              at jdk.compiler/com.sun.tools.javac.jvm.Code$State.forceStackTop(Code.java:1776)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.visitYield(Gen.java:1802)
              at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCYield.accept(JCTree.java:1658)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genDef(Gen.java:610)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genStat(Gen.java:645)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genStat(Gen.java:631)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genStats(Gen.java:682)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genStats(Gen.java:666)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.handleSwitch(Gen.java:1373)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.doHandleSwitchExpression(Gen.java:1238)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.visitSwitchExpression(Gen.java:1202)
              at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCSwitchExpression.accept(JCTree.java:1380)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genExpr(Gen.java:877)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.visitLetExpr(Gen.java:2381)
              at jdk.compiler/com.sun.tools.javac.tree.JCTree$LetExpr.accept(JCTree.java:3287)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genExpr(Gen.java:877)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.visitTypeCast(Gen.java:2228)
              at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCTypeCast.accept(JCTree.java:2185)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genExpr(Gen.java:877)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.visitReturn(Gen.java:1843)
              at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCReturn.accept(JCTree.java:1709)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genDef(Gen.java:610)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genStat(Gen.java:645)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genStat(Gen.java:631)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genStats(Gen.java:682)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.visitBlock(Gen.java:1097)
              at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:1091)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genDef(Gen.java:610)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genStat(Gen.java:645)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genMethod(Gen.java:967)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.visitMethodDef(Gen.java:930)
              at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:921)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genDef(Gen.java:610)
              at jdk.compiler/com.sun.tools.javac.jvm.Gen.genClass(Gen.java:2420)
              at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.genCode(JavaCompiler.java:737)
              at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1617)
              at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1585)
              at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:946)
              at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:317)
              at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:176)
              at jdk.compiler/com.sun.tools.javac.Main.compile(Main.java:64)
              at jdk.compiler/com.sun.tools.javac.Main.main(Main.java:50)

      ---------- BEGIN SOURCE ----------
      public class JFC {
          sealed interface I permits R1, R2 {}
          record R1() implements I {}
          record R2() implements I {}

          public static I foo(String cmd, String sub) {
              return (I) switch (cmd) {
                      case "$" -> switch (sub) {
                          case "ls" -> new R1();
                          case "cd" -> new R2();
                          default -> throw new IllegalArgumentException();
                      };
                      default -> new R1();
                  };
          }
      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      /* returning the redundant casting to the interface */
      public class JFC {
          sealed interface I permits R1, R2 {}
          record R1() implements I {}
          record R2() implements I {}

          public static I foo(String cmd, String sub) {
              return switch (cmd) {
                      case "$" -> switch (sub) {
                          case "ls" -> new R1();
                          case "cd" -> new R2();
                          default -> throw new IllegalArgumentException();
                      };
                      default -> new R1();
                  };
          }
      }

      /* Alternativly the records can be changed to static final classes */
      public class JFC {
          sealed interface I permits R1, R2 {}
          static final class R1 implements I {}
          static final class R2 implements I {}

          public static I foo(String cmd, String sub) {
              return (I) switch (cmd) {
                      case "$" -> switch (sub) {
                          case "ls" -> new R1();
                          case "cd" -> new R2();
                          default -> throw new IllegalArgumentException();
                      };
                      default -> new R1();
                  };
          }
      }

      FREQUENCY : always


            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: