diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index eb29d98632f6..f680e836bc1b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -136,7 +136,7 @@ jobs: - name: Cmd Tests run: | - ./project/scripts/sbt ";dist/pack; scala3-bootstrapped/compile; scala3-bootstrapped/test ;sbt-test/scripted scala2-compat/*; scala2-library-tasty-tests/test; scala3-compiler-bootstrapped/scala3CompilerCoursierTest:test" + ./project/scripts/sbt ";dist/pack; scala3-bootstrapped/compile; scala3-bootstrapped/test ;sbt-test/scripted scala2-compat/*; scala3-compiler-bootstrapped/scala3CompilerCoursierTest:test" ./project/scripts/cmdTests ./project/scripts/bootstrappedOnlyCmdTests @@ -547,7 +547,7 @@ jobs: - name: Test run: | - ./project/scripts/sbt ";dist/pack ;scala3-bootstrapped/compile ;scala3-bootstrapped/test ;sbt-test/scripted scala2-compat/*; scala2-library-tasty-tests/test" + ./project/scripts/sbt ";dist/pack ;scala3-bootstrapped/compile ;scala3-bootstrapped/test ;sbt-test/scripted scala2-compat/*" ./project/scripts/cmdTests ./project/scripts/bootstrappedOnlyCmdTests diff --git a/build.sbt b/build.sbt index 1712e80405ae..1bc74e5e23fb 100644 --- a/build.sbt +++ b/build.sbt @@ -16,7 +16,6 @@ val `scala3-bench-bootstrapped` = Build.`scala3-bench-bootstrapped` val `scala3-bench-micro` = Build.`scala3-bench-micro` val `scala2-library-bootstrapped` = Build.`scala2-library-bootstrapped` val `scala2-library-tasty` = Build.`scala2-library-tasty` -val `scala2-library-tasty-tests` = Build.`scala2-library-tasty-tests` val `scala2-library-cc` = Build.`scala2-library-cc` val `scala2-library-cc-tasty` = Build.`scala2-library-cc-tasty` val `tasty-core` = Build.`tasty-core` diff --git a/project/Build.scala b/project/Build.scala index 422582c6a217..4e7a0e5d0481 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1247,32 +1247,6 @@ object Build { }, ) - /** Test the tasty generated by `scala2-library-bootstrapped` - * - * The sources in src are compiled using TASTy from scala2-library-tasty but then run - * with the scala-library compiled be Scala 2. - * - * The tests are run with the bootstrapped compiler and the tasty inspector on the classpath. - * The classpath has the default `scala-library` and not `scala2-library-bootstrapped`. - * - * The jar of `scala2-library-bootstrapped` is provided for to the tests. - * - inspector: test that we can load the contents of the jar using the tasty inspector - * - from-tasty: test that we can recompile the contents of the jar using `dotc -from-tasty` - */ - lazy val `scala2-library-tasty-tests` = project.in(file("scala2-library-tasty-tests")). - withCommonSettings(Bootstrapped). - dependsOn(dottyCompiler(Bootstrapped) % "compile->compile"). - dependsOn(`scala3-tasty-inspector` % "test->test"). - dependsOn(`scala2-library-tasty`). - settings(commonBootstrappedSettings). - settings( - javaOptions := (`scala3-compiler-bootstrapped` / javaOptions).value, - Test / javaOptions += "-Ddotty.scala.library=" + (`scala2-library-bootstrapped` / Compile / packageBin).value.getAbsolutePath, - Compile / compile / fullClasspath ~= { - _.filterNot(file => file.data.getName == s"scala-library-$stdlibBootstrappedVersion.jar") - }, - ) - lazy val `scala3-sbt-bridge` = project.in(file("sbt-bridge/src")). // We cannot depend on any bootstrapped project to compile the bridge, since the // bridge is needed to compile these projects. diff --git a/scala2-library-tasty-tests/test/BootstrappedStdLibTASYyTest.scala b/scala2-library-tasty-tests/test/BootstrappedStdLibTASYyTest.scala deleted file mode 100644 index db810cd87f26..000000000000 --- a/scala2-library-tasty-tests/test/BootstrappedStdLibTASYyTest.scala +++ /dev/null @@ -1,174 +0,0 @@ -package dotty.tools.dotc - -import org.junit.Test -import org.junit.Ignore -import org.junit.Assert._ - -import dotty.tools.io._ -import dotty.tools.dotc.util.ClasspathFromClassloader - -import scala.quoted._ -import scala.tasty.inspector._ - -import java.io.File.pathSeparator -import java.io.File.separator - -class BootstrappedStdLibTASYyTest: - - import BootstrappedStdLibTASYyTest._ - - /** Test that we can load trees from TASTy */ - @Test def testTastyInspector: Unit = - loadWithTastyInspector(loadBlacklisted) - - /** Test that we can load and compile trees from TASTy in a Jar */ - @Test def testFromTastyInJar: Unit = - compileFromTastyInJar(loadBlacklisted.union(compileBlacklisted)) - - /** Test that we can load and compile trees from TASTy */ - @Test def testFromTasty: Unit = - compileFromTasty(loadBlacklisted.union(compileBlacklisted)) - - @Test def blacklistNoDuplicates = - def testDup(name: String, list: List[String], set: Set[String]) = - assert(list.size == set.size, - list.diff(set.toSeq).mkString(s"`$name` has duplicate entries:\n ", "\n ", "\n\n")) - testDup("loadBlacklist", loadBlacklist, loadBlacklisted) - testDup("compileBlacklist", compileBlacklist, compileBlacklisted) - - @Test def blacklistsNoIntersection = - val intersection = loadBlacklisted & compileBlacklisted - assert(intersection.isEmpty, - intersection.mkString( - "`compileBlacklist` contains names that are already in `loadBlacklist`: \n ", "\n ", "\n\n")) - - @Test def blacklistsOnlyContainsClassesThatExist = - val scalaLibTastyPathsSet = scalaLibTastyPaths.toSet - val intersection = loadBlacklisted & compileBlacklisted - assert(loadBlacklisted.diff(scalaLibTastyPathsSet).isEmpty, - loadBlacklisted.diff(scalaLibTastyPathsSet).mkString( - "`loadBlacklisted` contains names that are not in `scalaLibTastyPaths`: \n ", "\n ", "\n\n")) - assert(compileBlacklisted.diff(scalaLibTastyPathsSet).isEmpty, - compileBlacklisted.diff(scalaLibTastyPathsSet).mkString( - "`loadBlacklisted` contains names that are not in `scalaLibTastyPaths`: \n ", "\n ", "\n\n")) - - @Ignore - @Test def testLoadBacklistIsMinimal = - var shouldBeWhitelisted = List.empty[String] - val size = loadBlacklisted.size - for (notBlacklisted, i) <- loadBlacklist.zipWithIndex do - val blacklist = loadBlacklisted - notBlacklisted - println(s"Trying without $notBlacklisted in the blacklist (${i+1}/$size)") - try { - loadWithTastyInspector(blacklist) - shouldBeWhitelisted = notBlacklisted :: shouldBeWhitelisted - } - catch { - case ex: Throwable => // ok - } - assert(shouldBeWhitelisted.isEmpty, - shouldBeWhitelisted.mkString("Some classes do not need to be blacklisted in `loadBlacklisted`\n ", "\n ", "\n\n")) - - @Ignore - @Test def testCompileBlacklistIsMinimal = - var shouldBeWhitelisted = List.empty[String] - val size = compileBlacklisted.size - val blacklist0 = loadBlacklisted.union(compileBlacklisted) - for (notBlacklisted, i) <- compileBlacklist.zipWithIndex do - val blacklist = blacklist0 - notBlacklisted - println(s"Trying without $notBlacklisted in the blacklist (${i+1}/$size)") - try { - compileFromTastyInJar(blacklist) - shouldBeWhitelisted = notBlacklisted :: shouldBeWhitelisted - } - catch { - case ex: Throwable => // ok - } - assert(shouldBeWhitelisted.isEmpty, - shouldBeWhitelisted.mkString("Some classes do not need to be blacklisted in `compileBlacklisted`\n ", "\n ", "\n\n")) - -end BootstrappedStdLibTASYyTest - -object BootstrappedStdLibTASYyTest: - - def scalaLibJarPath = System.getProperty("dotty.scala.library") - def scalaLibClassesPath = - java.nio.file.Paths.get(scalaLibJarPath).getParent.resolve("classes").normalize - - val scalaLibTastyPaths = - new Directory(scalaLibClassesPath).deepFiles - .filter(_.`extension` == "tasty") - .map(_.normalize.path.stripPrefix(scalaLibClassesPath.toString + "/")) - .toList - - def loadWithTastyInspector(blacklisted: Set[String]): Unit = - val inspector = new scala.tasty.inspector.Inspector { - def inspect(using Quotes)(tastys: List[Tasty[quotes.type]]): Unit = - for tasty <- tastys do - tasty.ast.show(using quotes.reflect.Printer.TreeStructure) // Check that we can traverse the full tree - () - } - val tastyFiles = scalaLibTastyPaths.filterNot(blacklisted) - val isSuccess = TastyInspector.inspectTastyFiles(tastyFiles.map(x => scalaLibClassesPath.resolve(x).toString))(inspector) - assert(isSuccess, "Errors reported while loading from TASTy") - - def compileFromTastyInJar(blacklisted: Set[String]): Unit = { - val driver = new dotty.tools.dotc.Driver - val yFromTastyBlacklist = - blacklisted.mkString("-Yfrom-tasty-ignore-list:", ",", "") - val args = Array( - "-classpath", ClasspathFromClassloader(getClass.getClassLoader), - "-from-tasty", - "-nowarn", - yFromTastyBlacklist, - scalaLibJarPath, - ) - val reporter = driver.process(args) - assert(reporter.errorCount == 0, "Errors while re-compiling") - } - - def compileFromTasty(blacklisted: Set[String]): Unit = { - val driver = new dotty.tools.dotc.Driver - val tastyFiles = scalaLibTastyPaths.filterNot(blacklisted) - val args = Array( - "-classpath", ClasspathFromClassloader(getClass.getClassLoader), - "-from-tasty", - "-nowarn", - ) ++ tastyFiles.map(x => scalaLibClassesPath.resolve(x).toString) - val reporter = driver.process(args) - assert(reporter.errorCount == 0, "Errors while re-compiling") - } - - /** List of tasty files that cannot be loaded from TASTy */ - def loadBlacklist = List[String]( - // No issues :) - ) - - /** List of tasty files that cannot be recompilied from TASTy */ - def compileBlacklist = List[String]( - // See #10048 - // failed: java.lang.AssertionError: assertion failed: class Boolean - // at dotty.tools.backend.jvm.BCodeHelpers$BCInnerClassGen.assertClassNotArrayNotPrimitive(BCodeHelpers.scala:247) - // at dotty.tools.backend.jvm.BCodeHelpers$BCInnerClassGen.getClassBTypeAndRegisterInnerClass(BCodeHelpers.scala:265) - // at dotty.tools.backend.jvm.BCodeHelpers$BCInnerClassGen.getClassBTypeAndRegisterInnerClass$(BCodeHelpers.scala:210) - // at dotty.tools.backend.jvm.BCodeSkelBuilder$PlainSkelBuilder.getClassBTypeAndRegisterInnerClass(BCodeSkelBuilder.scala:62) - // at dotty.tools.backend.jvm.BCodeHelpers$BCInnerClassGen.internalName(BCodeHelpers.scala:237) - "scala/Array.tasty", - "scala/Boolean.tasty", - "scala/Byte.tasty", - "scala/Char.tasty", - "scala/Double.tasty", - "scala/Float.tasty", - "scala/Int.tasty", - "scala/Long.tasty", - "scala/Short.tasty", - "scala/Unit.tasty", - ).map(_.replace("/", separator)) - - /** Set of tasty files that cannot be loaded from TASTy */ - def loadBlacklisted = loadBlacklist.toSet - - /** Set of tasty files that cannot be recompilied from TASTy */ - def compileBlacklisted = compileBlacklist.toSet - -end BootstrappedStdLibTASYyTest diff --git a/tests/run-tasty-inspector/scala2-library-test.scala b/tests/run-tasty-inspector/scala2-library-test.scala new file mode 100644 index 000000000000..94604120d6c7 --- /dev/null +++ b/tests/run-tasty-inspector/scala2-library-test.scala @@ -0,0 +1,52 @@ +import scala.quoted._ +import scala.tasty.inspector._ + +import dotty.tools.io.Directory + +import java.io.File.pathSeparator + +@main def Test: Unit = + blacklistsOnlyContainsClassesThatExist() + testTastyInspector() + +/** Test that we can load trees from TASTy */ +def testTastyInspector(): Unit = + loadWithTastyInspector(loadBlacklisted) + +def blacklistsOnlyContainsClassesThatExist() = + val scalaLibTastyPathsSet = scalaLibTastyPaths.toSet + assert(loadBlacklisted.diff(scalaLibTastyPathsSet).isEmpty, + loadBlacklisted.diff(scalaLibTastyPathsSet).mkString( + "`loadBlacklisted` contains names that are not in `scalaLibTastyPaths`: \n ", "\n ", "\n\n")) + +def dottyVersion = + System.getProperty("java.class.path").nn.split(pathSeparator).collectFirst { + case path if path.endsWith(".jar") && path.contains("/scala3-library_3-") => + path.split("/scala3-library_3-").last.stripSuffix(".jar") + }.get + +def scalaLibClassesPath = + java.nio.file.Paths.get( + s"out/bootstrap/scala2-library-bootstrapped/scala-$dottyVersion-nonbootstrapped/classes") + +lazy val scalaLibTastyPaths = + new Directory(scalaLibClassesPath).deepFiles + .filter(_.`extension` == "tasty") + .map(_.normalize.path.stripPrefix(scalaLibClassesPath.toString + "/")) + .toList + +def loadWithTastyInspector(blacklisted: Set[String]): Unit = + val inspector = new scala.tasty.inspector.Inspector { + def inspect(using Quotes)(tastys: List[Tasty[quotes.type]]): Unit = + for tasty <- tastys do + tasty.ast.show(using quotes.reflect.Printer.TreeStructure) // Check that we can traverse the full tree + () + } + val tastyFiles = scalaLibTastyPaths.filterNot(blacklisted) + val isSuccess = TastyInspector.inspectTastyFiles(tastyFiles.map(x => scalaLibClassesPath.resolve(x).toString))(inspector) + assert(isSuccess, "Errors reported while loading from TASTy") + +/** Set of tasty files that cannot be loaded from TASTy */ +def loadBlacklisted = Set[String]( + // No issues :) +) diff --git a/tests/run-with-compiler/scala2-library-from-tasty.scala b/tests/run-with-compiler/scala2-library-from-tasty.scala new file mode 100644 index 000000000000..0b6e1766b9a0 --- /dev/null +++ b/tests/run-with-compiler/scala2-library-from-tasty.scala @@ -0,0 +1,91 @@ +import dotty.tools.io.Directory +import dotty.tools.dotc.util.ClasspathFromClassloader + +import java.io.File.pathSeparator +import java.io.File.separator + +@main def Test: Unit = + blacklistsOnlyContainsClassesThatExist() + testFromTastyInJar() + testFromTasty() + +/** Test that we can load and compile trees from TASTy in a Jar */ +def testFromTastyInJar(): Unit = + compileFromTastyInJar(compileBlacklisted) + +/** Test that we can load and compile trees from TASTy */ +def testFromTasty(): Unit = + compileFromTasty(compileBlacklisted) + +def blacklistsOnlyContainsClassesThatExist() = + val scalaLibTastyPathsSet = scalaLibTastyPaths.toSet + assert(compileBlacklisted.diff(scalaLibTastyPathsSet).isEmpty, + compileBlacklisted.diff(scalaLibTastyPathsSet).mkString( + "`loadBlacklisted` contains names that are not in `scalaLibTastyPaths`: \n ", "\n ", "\n\n")) + +def dottyVersion = + System.getProperty("java.class.path").nn.split(pathSeparator).collectFirst { + case path if path.endsWith(".jar") && path.contains("/scala3-library_3-") => + path.split("/scala3-library_3-").last.stripSuffix(".jar") + }.get + +def scalaLibJarPath = + s"out/bootstrap/scala2-library-tasty/scala-$dottyVersion-nonbootstrapped/scala2-library-tasty_3-$dottyVersion.jar" + +def scalaLibClassesPath = + java.nio.file.Paths.get( + s"out/bootstrap/scala2-library-bootstrapped/scala-$dottyVersion-nonbootstrapped/classes") + +lazy val scalaLibTastyPaths = + new Directory(scalaLibClassesPath).deepFiles + .filter(_.`extension` == "tasty") + .map(_.normalize.path.stripPrefix(scalaLibClassesPath.toString + "/")) + .toList + +def compileFromTastyInJar(blacklisted: Set[String]): Unit = { + val driver = new dotty.tools.dotc.Driver + val yFromTastyBlacklist = + blacklisted.mkString("-Yfrom-tasty-ignore-list:", ",", "") + val args = Array( + "-classpath", ClasspathFromClassloader(getClass.getClassLoader), + "-from-tasty", + "-nowarn", + yFromTastyBlacklist, + scalaLibJarPath, + ) + val reporter = driver.process(args) + assert(reporter.errorCount == 0, "Errors while re-compiling") +} + +def compileFromTasty(blacklisted: Set[String]): Unit = { + val driver = new dotty.tools.dotc.Driver + val tastyFiles = scalaLibTastyPaths.filterNot(blacklisted) + val args = Array( + "-classpath", ClasspathFromClassloader(getClass.getClassLoader), + "-from-tasty", + "-nowarn", + ) ++ tastyFiles.map(x => scalaLibClassesPath.resolve(x).toString) + val reporter = driver.process(args) + assert(reporter.errorCount == 0, "Errors while re-compiling") +} + +/** Set of tasty files that cannot be recompiled from TASTy */ +def compileBlacklisted = Set[String]( + // See #10048 + // failed: java.lang.AssertionError: assertion failed: class Boolean + // at dotty.tools.backend.jvm.BCodeHelpers$BCInnerClassGen.assertClassNotArrayNotPrimitive(BCodeHelpers.scala:247) + // at dotty.tools.backend.jvm.BCodeHelpers$BCInnerClassGen.getClassBTypeAndRegisterInnerClass(BCodeHelpers.scala:265) + // at dotty.tools.backend.jvm.BCodeHelpers$BCInnerClassGen.getClassBTypeAndRegisterInnerClass$(BCodeHelpers.scala:210) + // at dotty.tools.backend.jvm.BCodeSkelBuilder$PlainSkelBuilder.getClassBTypeAndRegisterInnerClass(BCodeSkelBuilder.scala:62) + // at dotty.tools.backend.jvm.BCodeHelpers$BCInnerClassGen.internalName(BCodeHelpers.scala:237) + "scala/Array.tasty", + "scala/Boolean.tasty", + "scala/Byte.tasty", + "scala/Char.tasty", + "scala/Double.tasty", + "scala/Float.tasty", + "scala/Int.tasty", + "scala/Long.tasty", + "scala/Short.tasty", + "scala/Unit.tasty", +).map(_.replace("/", separator))