From d9c84b96de92048de0e94ade74612d352c959b8c Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 13 Nov 2023 14:26:18 +0100 Subject: [PATCH 1/2] Allow cross compilation tests with Scala 2 compiler --- .../dotty/tools/vulpix/ParallelTesting.scala | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index 4804ffd349cb..5d3c8f59a852 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -610,17 +610,38 @@ trait ParallelTesting extends RunnerOrchestration { self => .run() .mkString(JFile.pathSeparator) - val stdlibClasspath = artifactClasspath("org.scala-lang", "scala3-library_3") - val scalacClasspath = artifactClasspath("org.scala-lang", "scala3-compiler_3") - val pageWidth = TestConfiguration.pageWidth - 20 - val flags1 = flags.copy(defaultClassPath = stdlibClasspath) - .withClasspath(targetDir.getPath) - .and("-d", targetDir.getPath) - .and("-pagewidth", pageWidth.toString) - val scalacCommand = Array("java", "-cp", scalacClasspath, "dotty.tools.dotc.Main") - val command = scalacCommand ++ flags1.all ++ files.map(_.getAbsolutePath) + val fileArgs = files.map(_.getAbsolutePath) + + def scala2Command(): Array[String] = { + assert(!flags.options.contains("-scalajs"), + "Compilation tests with Scala.js on Scala 2 are not supported.\nThis test can be blacklisted in compiler/test/dotc/*-scala-js.blacklist") + val stdlibClasspath = artifactClasspath("org.scala-lang", "scala-library") + val scalacClasspath = artifactClasspath("org.scala-lang", "scala-compiler") + val flagsArgs = flags + .copy(options = Array.empty, defaultClassPath = stdlibClasspath) + .withClasspath(targetDir.getPath) + .and("-d", targetDir.getPath) + .all + val scalacCommand = Array("java", "-cp", scalacClasspath, "scala.tools.nsc.Main") + scalacCommand ++ flagsArgs ++ fileArgs + } + + def scala3Command(): Array[String] = { + val stdlibClasspath = artifactClasspath("org.scala-lang", "scala3-library_3") + val scalacClasspath = artifactClasspath("org.scala-lang", "scala3-compiler_3") + val flagsArgs = flags + .copy(defaultClassPath = stdlibClasspath) + .withClasspath(targetDir.getPath) + .and("-d", targetDir.getPath) + .and("-pagewidth", pageWidth.toString) + .all + val scalacCommand = Array("java", "-cp", scalacClasspath, "dotty.tools.dotc.Main") + scalacCommand ++ flagsArgs ++ fileArgs + } + + val command = if compiler.startsWith("2") then scala2Command() else scala3Command() val process = Runtime.getRuntime.exec(command) val reporter = mkReporter From b035f76a3a51167b5646e9317431e69630166c5b Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 13 Nov 2023 11:09:53 +0100 Subject: [PATCH 2/2] Reinterpret `xyz$access$i` when unpickling from Scala 2 Fixes #18884 --- .../dotc/core/unpickleScala2/Scala2Unpickler.scala | 8 ++++++++ .../tools/backend/jvm/DottyBytecodeTests.scala | 4 ++-- .../test/dotty/tools/vulpix/ParallelTesting.scala | 2 +- tests/neg/i18884.scala | 2 ++ tests/run/i18884.check | 4 ++++ tests/run/i18884/A_1_c2.13.12.scala | 10 ++++++++++ tests/run/i18884/B_2.scala | 14 ++++++++++++++ tests/run/typeclass-derivation3.check | 6 +++--- 8 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 tests/neg/i18884.scala create mode 100644 tests/run/i18884.check create mode 100644 tests/run/i18884/A_1_c2.13.12.scala create mode 100644 tests/run/i18884/B_2.scala diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 4381c9a2f52c..b5ee0e0525b4 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -462,6 +462,14 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas flags &~= Method | Accessor if !flags.is(StableRealizable) then flags |= Mutable + // Skip case accessor `$access$` and keep track of their name to make `` the case accessor + if flags.is(CaseAccessor) && name.toString().contains("$access$") then + val accessorName = name.toString().split('$').head.toTermName // + symScope(owner) // we assume that the `` is listed before the accessor and hence is already entered in the scope + .find(decl => decl.isAllOf(ParamAccessor) && decl.name == accessorName) + .setFlag(CaseAccessor) + return NoSymbol // skip this member + name = name.adjustIfModuleClass(flags) if (flags.is(Method)) name = diff --git a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala index 84c7b916fa74..94d42952a6eb 100644 --- a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala +++ b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala @@ -1058,7 +1058,7 @@ class DottyBytecodeTests extends DottyBytecodeTest { TypeOp(CHECKCAST, "scala/collection/immutable/$colon$colon"), VarOp(ASTORE, 3), VarOp(ALOAD, 3), - Invoke(INVOKEVIRTUAL, "scala/collection/immutable/$colon$colon", "next$access$1", "()Lscala/collection/immutable/List;", false), + Invoke(INVOKEVIRTUAL, "scala/collection/immutable/$colon$colon", "next", "()Lscala/collection/immutable/List;", false), VarOp(ASTORE, 4), VarOp(ALOAD, 3), Invoke(INVOKEVIRTUAL, "scala/collection/immutable/$colon$colon", "head", "()Ljava/lang/Object;", false), @@ -1112,7 +1112,7 @@ class DottyBytecodeTests extends DottyBytecodeTest { Invoke(INVOKESTATIC, "scala/runtime/BoxesRunTime", "unboxToInt", "(Ljava/lang/Object;)I", false), VarOp(ISTORE, 4), VarOp(ALOAD, 3), - Invoke(INVOKEVIRTUAL, "scala/collection/immutable/$colon$colon", "next$access$1", "()Lscala/collection/immutable/List;", false), + Invoke(INVOKEVIRTUAL, "scala/collection/immutable/$colon$colon", "next", "()Lscala/collection/immutable/List;", false), VarOp(ASTORE, 5), Op(ICONST_1), VarOp(ILOAD, 4), diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index 5d3c8f59a852..e93a0435987b 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -616,7 +616,7 @@ trait ParallelTesting extends RunnerOrchestration { self => def scala2Command(): Array[String] = { assert(!flags.options.contains("-scalajs"), - "Compilation tests with Scala.js on Scala 2 are not supported.\nThis test can be blacklisted in compiler/test/dotc/*-scala-js.blacklist") + "Compilation tests with Scala.js on Scala 2 are not supported.\nThis test can be skipped using the `// scalajs: --skip` tag") val stdlibClasspath = artifactClasspath("org.scala-lang", "scala-library") val scalacClasspath = artifactClasspath("org.scala-lang", "scala-compiler") val flagsArgs = flags diff --git a/tests/neg/i18884.scala b/tests/neg/i18884.scala new file mode 100644 index 000000000000..6ba17fde7f70 --- /dev/null +++ b/tests/neg/i18884.scala @@ -0,0 +1,2 @@ +def test(xs: ::[Int]): List[Int] = + xs.next$access$1 // error diff --git a/tests/run/i18884.check b/tests/run/i18884.check new file mode 100644 index 000000000000..e70c450a107a --- /dev/null +++ b/tests/run/i18884.check @@ -0,0 +1,4 @@ +Foo1(1) +Foo2(2, 3) +Foo3(4, 5) +Foo4(6, 7) diff --git a/tests/run/i18884/A_1_c2.13.12.scala b/tests/run/i18884/A_1_c2.13.12.scala new file mode 100644 index 000000000000..23a2bee52ba5 --- /dev/null +++ b/tests/run/i18884/A_1_c2.13.12.scala @@ -0,0 +1,10 @@ +// scalajs: --skip + +package lib + +case class Foo1(private[lib] var x: Int) {} +case class Foo2(private[lib] var x: Int, private[lib] var y: Int) +case class Foo3(private[lib] var x: Int, var y: Int) +case class Foo4(var x: Int, private[lib] var y: Int) { + val z: Int = x +} diff --git a/tests/run/i18884/B_2.scala b/tests/run/i18884/B_2.scala new file mode 100644 index 000000000000..5c775529b953 --- /dev/null +++ b/tests/run/i18884/B_2.scala @@ -0,0 +1,14 @@ +import lib.* + +@main def Test: Unit = + test(new Foo1(1)) + test(new Foo2(2, 3)) + test(new Foo3(4, 5)) + test(new Foo4(6, 7)) + +def test(any: Any): Unit = + any match + case Foo1(x) => println(s"Foo1($x)") + case Foo2(x, y) => println(s"Foo2($x, $y)") + case Foo3(x, y) => println(s"Foo3($x, $y)") + case Foo4(x, y) => println(s"Foo4($x, $y)") diff --git a/tests/run/typeclass-derivation3.check b/tests/run/typeclass-derivation3.check index 12bb24628b0c..34b8a6b81f7e 100644 --- a/tests/run/typeclass-derivation3.check +++ b/tests/run/typeclass-derivation3.check @@ -9,6 +9,6 @@ Cons(hd = Cons(hd = 11, tl = Cons(hd = 22, tl = Cons(hd = 33, tl = Nil))), tl = Cons(hd = Left(x = 1), tl = Cons(hd = Right(x = Pair(x = 2, y = 3)), tl = Nil)) Cons(hd = Left(x = 1), tl = Cons(hd = Right(x = Pair(x = 2, y = 3)), tl = Nil)) true -::(head = 1, next$access$1 = ::(head = 2, next$access$1 = ::(head = 3, next$access$1 = Nil()))) -::(head = ::(head = 1, next$access$1 = Nil()), next$access$1 = ::(head = ::(head = 2, next$access$1 = ::(head = 3, next$access$1 = Nil())), next$access$1 = Nil())) -::(head = Nil(), next$access$1 = ::(head = ::(head = 1, next$access$1 = Nil()), next$access$1 = ::(head = ::(head = 2, next$access$1 = ::(head = 3, next$access$1 = Nil())), next$access$1 = Nil()))) +::(head = 1, next = ::(head = 2, next = ::(head = 3, next = Nil()))) +::(head = ::(head = 1, next = Nil()), next = ::(head = ::(head = 2, next = ::(head = 3, next = Nil())), next = Nil())) +::(head = Nil(), next = ::(head = ::(head = 1, next = Nil()), next = ::(head = ::(head = 2, next = ::(head = 3, next = Nil())), next = Nil())))