From 0c3933f4449bce336ae8ce4eb849f7b0d1d048bd Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 26 Jan 2024 10:20:04 -0500 Subject: [PATCH 1/2] forward-port ClassfileParserTest from Scala 2 Co-authored-by: Lukas Rytz --- .../backend/jvm/ClassfileParserTest.scala | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 compiler/test/dotty/tools/backend/jvm/ClassfileParserTest.scala 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..8103812a3865 --- /dev/null +++ b/compiler/test/dotty/tools/backend/jvm/ClassfileParserTest.scala @@ -0,0 +1,54 @@ +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_FIELDREF", + "CONSTANT_FLOAT", + "CONSTANT_INTEGER", + "CONSTANT_INTFMETHODREF", + "CONSTANT_INVOKEDYNAMIC", + "CONSTANT_LONG", + "CONSTANT_METHODHANDLE", + "CONSTANT_METHODREF", + "CONSTANT_METHODTYPE", + "CONSTANT_NAMEANDTYPE", + "CONSTANT_STRING", + "CONSTANT_UNICODE", + "CONSTANT_UTF8", + )) + } +} From 26852deba278185eb62bc305c5e863ad93f52dbc Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 25 Jan 2024 19:14:17 -0500 Subject: [PATCH 2/2] classfile reader: allow JDK 9+ constant types in constant pool forward-port of scala/scala#10675 and scala/scala#8595 references scala/bug#12396 and scala/bug#11635 fixes lampepfl/dotty#19527 ("bad constant pool tag 17") also fixes unreported potential "bad constant pool tag 19" and "bad constant pool tag 20" errors --- .../core/classfile/ClassfileConstants.scala | 3 +++ .../dotc/core/classfile/ClassfileParser.scala | 5 +++-- .../tools/backend/jvm/ClassfileParserTest.scala | 3 +++ tests/pos/t12396/A_1.java | 17 +++++++++++++++++ tests/pos/t12396/B_2.scala | 5 +++++ 5 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 tests/pos/t12396/A_1.java create mode 100644 tests/pos/t12396/B_2.scala 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 93ebcfeee62a..894d430fe54b 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -106,13 +106,14 @@ object 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 index 8103812a3865..9263103f1712 100644 --- a/compiler/test/dotty/tools/backend/jvm/ClassfileParserTest.scala +++ b/compiler/test/dotty/tools/backend/jvm/ClassfileParserTest.scala @@ -36,6 +36,7 @@ class ClassfileParserTest { // in ClassfileConstants! that would defeat the purpose of the test "CONSTANT_CLASS", "CONSTANT_DOUBLE", + "CONSTANT_DYNAMIC", "CONSTANT_FIELDREF", "CONSTANT_FLOAT", "CONSTANT_INTEGER", @@ -45,7 +46,9 @@ class ClassfileParserTest { "CONSTANT_METHODHANDLE", "CONSTANT_METHODREF", "CONSTANT_METHODTYPE", + "CONSTANT_MODULE", "CONSTANT_NAMEANDTYPE", + "CONSTANT_PACKAGE", "CONSTANT_STRING", "CONSTANT_UNICODE", "CONSTANT_UTF8", 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) +}