diff --git a/compiler/src/dotty/tools/backend/jvm/BackendUtils.scala b/compiler/src/dotty/tools/backend/jvm/BackendUtils.scala index 973e9cddcadd..1b16b2bc9800 100644 --- a/compiler/src/dotty/tools/backend/jvm/BackendUtils.scala +++ b/compiler/src/dotty/tools/backend/jvm/BackendUtils.scala @@ -186,6 +186,7 @@ object BackendUtils { 21 -> asm.Opcodes.V21, 22 -> asm.Opcodes.V22, 23 -> asm.Opcodes.V23, - 24 -> asm.Opcodes.V24 + 24 -> asm.Opcodes.V24, + 25 -> asm.Opcodes.V25 ) } diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileConstants.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileConstants.scala index 6ad71c5fd1ce..7a2232891a83 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileConstants.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileConstants.scala @@ -73,7 +73,10 @@ object ClassfileConstants { inline val CONSTANT_METHODHANDLE = 15 inline val CONSTANT_METHODTYPE = 16 + inline val CONSTANT_DYNAMIC = 17 inline val CONSTANT_INVOKEDYNAMIC = 18 + inline val CONSTANT_MODULE = 19 + inline val CONSTANT_PACKAGE = 20 // tags describing the type of a literal in attribute values inline val BYTE_TAG = 'B' diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index c20b6c73b1ea..520be41ba7f9 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -1224,13 +1224,14 @@ class ClassfileParser( (in.nextByte.toInt: @switch) match { case CONSTANT_UTF8 | CONSTANT_UNICODE => in.skip(in.nextChar) - case CONSTANT_CLASS | CONSTANT_STRING | CONSTANT_METHODTYPE => + case CONSTANT_CLASS | CONSTANT_STRING | CONSTANT_METHODTYPE + | CONSTANT_MODULE | CONSTANT_PACKAGE => in.skip(2) case CONSTANT_METHODHANDLE => in.skip(3) case CONSTANT_FIELDREF | CONSTANT_METHODREF | CONSTANT_INTFMETHODREF | CONSTANT_NAMEANDTYPE | CONSTANT_INTEGER | CONSTANT_FLOAT - | CONSTANT_INVOKEDYNAMIC => + | CONSTANT_INVOKEDYNAMIC | CONSTANT_DYNAMIC => in.skip(4) case CONSTANT_LONG | CONSTANT_DOUBLE => in.skip(8) diff --git a/compiler/test/dotty/tools/backend/jvm/ClassfileParserTest.scala b/compiler/test/dotty/tools/backend/jvm/ClassfileParserTest.scala new file mode 100644 index 000000000000..9263103f1712 --- /dev/null +++ b/compiler/test/dotty/tools/backend/jvm/ClassfileParserTest.scala @@ -0,0 +1,57 @@ +package dotty.tools.backend.jvm + +// painful to do Java reflection stuff without this +import scala.language.unsafeNulls + +import org.junit.Assert.assertEquals +import org.junit.Test + +import java.lang.reflect.Member + +class ClassfileParserTest { + @Test + def noConstantPoolLag(): Unit = { + def constNames(ms: List[Member]) = ms.collect { + case f if f.getName.startsWith("CONSTANT_") => f.getName + }.sorted + + val toDotc = Map( + "CONSTANT_INTERFACE_METHODREF" -> "CONSTANT_INTFMETHODREF", + "CONSTANT_INVOKE_DYNAMIC" -> "CONSTANT_INVOKEDYNAMIC", + "CONSTANT_METHOD_HANDLE" -> "CONSTANT_METHODHANDLE", + "CONSTANT_METHOD_TYPE" -> "CONSTANT_METHODTYPE", + "CONSTANT_NAME_AND_TYPE" -> "CONSTANT_NAMEANDTYPE", + ).withDefault(x => x) + + val asmConsts = constNames(Class.forName("scala.tools.asm.Symbol").getDeclaredFields.toList) + .map(_.stripSuffix("_TAG")) + .map(toDotc) + .::("CONSTANT_UNICODE") + .sorted + // in the Scala 2 version of this test, we also use Java reflection to get the constant + // names out of ClassfileConstants. in Dotty, the constants are `inline val`s, invisible + // to Java reflection, so we hardcode them here + assertEquals(asmConsts, List( + // do not add to this list without also making the corresponding change + // in ClassfileConstants! that would defeat the purpose of the test + "CONSTANT_CLASS", + "CONSTANT_DOUBLE", + "CONSTANT_DYNAMIC", + "CONSTANT_FIELDREF", + "CONSTANT_FLOAT", + "CONSTANT_INTEGER", + "CONSTANT_INTFMETHODREF", + "CONSTANT_INVOKEDYNAMIC", + "CONSTANT_LONG", + "CONSTANT_METHODHANDLE", + "CONSTANT_METHODREF", + "CONSTANT_METHODTYPE", + "CONSTANT_MODULE", + "CONSTANT_NAMEANDTYPE", + "CONSTANT_PACKAGE", + "CONSTANT_STRING", + "CONSTANT_UNICODE", + "CONSTANT_UTF8", + )) + } +} diff --git a/project/Build.scala b/project/Build.scala index acb384a75416..6cdb32ebb0c5 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -662,7 +662,7 @@ object Build { // get libraries onboard libraryDependencies ++= Seq( - "org.scala-lang.modules" % "scala-asm" % "9.7.1-scala-1", // used by the backend + "org.scala-lang.modules" % "scala-asm" % "9.8.0-scala-1", // used by the backend Dependencies.compilerInterface, "org.jline" % "jline-reader" % "3.27.1", // used by the REPL "org.jline" % "jline-terminal" % "3.27.1", diff --git a/tests/pos/t12396/A_1.java b/tests/pos/t12396/A_1.java new file mode 100644 index 000000000000..a394d3a0a59d --- /dev/null +++ b/tests/pos/t12396/A_1.java @@ -0,0 +1,17 @@ +// test: -jvm 21+ + +public class A_1 { + public int f(Object s) { + switch(s) { + case Res.R -> { + return 1; + } + default -> { + return 3; + } + } + } + static enum Res { + R + } +} diff --git a/tests/pos/t12396/B_2.scala b/tests/pos/t12396/B_2.scala new file mode 100644 index 000000000000..662da7b3a575 --- /dev/null +++ b/tests/pos/t12396/B_2.scala @@ -0,0 +1,5 @@ +// test: -jvm 21+ + +class B { + def bar = (new A_1).f(null) +}