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
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