diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 71a2c4ed6eb0..c269d8667406 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -141,7 +141,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 @@ -584,7 +584,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/compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala b/compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala index 2f4ecad8859d..98ab8e2b6226 100644 --- a/compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala +++ b/compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala @@ -22,9 +22,9 @@ class TASTYRun(comp: Compiler, ictx: Context) extends Run(comp, ictx) { file.extension match case "jar" => JarArchive.open(Path(file.path), create = false).allFileNames() - .map(_.stripPrefix(File.separator)) // change paths from absolute to relative - .filter(e => Path.extension(e) == "tasty" && !fromTastyIgnoreList(e)) - .map(e => e.stripSuffix(".tasty").replace(File.separator, ".")) + .map(_.stripPrefix("/")) // change paths from absolute to relative + .filter(e => Path.extension(e) == "tasty" && !fromTastyIgnoreList(e.replace("/", File.separator))) + .map(e => e.stripSuffix(".tasty").replace("/", ".")) .toList case "tasty" => TastyFileUtil.getClassName(file) case _ => diff --git a/project/Build.scala b/project/Build.scala index 19bb9a7c0419..fb94a7da68fa 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1250,32 +1250,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..15a251427d70 --- /dev/null +++ b/tests/run-tasty-inspector/scala2-library-test.scala @@ -0,0 +1,53 @@ +import scala.quoted._ +import scala.tasty.inspector._ + +import dotty.tools.io.Directory + +import java.io.File.pathSeparator +import java.io.File.separator + +@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".replace("/", separator)) + +lazy val scalaLibTastyPaths = + new Directory(scalaLibClassesPath).deepFiles + .filter(_.`extension` == "tasty") + .map(_.normalize.path.stripPrefix(scalaLibClassesPath.toString + separator)) + .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-jar.scala b/tests/run-with-compiler/scala2-library-from-tasty-jar.scala new file mode 100644 index 000000000000..913cf7dc24fc --- /dev/null +++ b/tests/run-with-compiler/scala2-library-from-tasty-jar.scala @@ -0,0 +1,74 @@ +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() + // FIXME this test does not work on JDK8 + // Caused by: dotty.tools.dotc.core.TypeError$$anon$1: package scala.quoted.runtime.Expr does not have a member method quote + if System.getProperty("java.specification.version") != "1.8" then + compileFromTastyInJar(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${separator}bootstrap${separator}scala2-library-tasty${separator}scala-$dottyVersion-nonbootstrapped${separator}scala2-library-tasty-experimental_3-$dottyVersion.jar" + +def scalaLibClassesPath = + java.nio.file.Paths.get( + s"out${separator}bootstrap${separator}scala2-library-bootstrapped${separator}scala-$dottyVersion-nonbootstrapped${separator}classes") + +lazy val scalaLibTastyPaths = + new Directory(scalaLibClassesPath).deepFiles + .filter(_.`extension` == "tasty") + .map(_.normalize.path.stripPrefix(scalaLibClassesPath.toString + separator)) + .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", + "-d", s"out${separator}scala2-library-from-tasty-jar-test-output.jar", + "-nowarn", + yFromTastyBlacklist, + scalaLibJarPath, + ) + 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) + s"scala${separator}Array.tasty", + s"scala${separator}Boolean.tasty", + s"scala${separator}Byte.tasty", + s"scala${separator}Char.tasty", + s"scala${separator}Double.tasty", + s"scala${separator}Float.tasty", + s"scala${separator}Int.tasty", + s"scala${separator}Long.tasty", + s"scala${separator}Short.tasty", + s"scala${separator}Unit.tasty", +) 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..ee2ec8951701 --- /dev/null +++ b/tests/run-with-compiler/scala2-library-from-tasty.scala @@ -0,0 +1,68 @@ +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() + // FIXME this test does not work on JDK8 + // Caused by: dotty.tools.dotc.core.TypeError$$anon$1: package scala.quoted.runtime.Expr does not have a member method quote + if System.getProperty("java.specification.version") != "1.8" then + 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 scalaLibClassesPath = + java.nio.file.Paths.get( + s"out${separator}bootstrap${separator}scala2-library-bootstrapped${separator}scala-$dottyVersion-nonbootstrapped${separator}classes") + +lazy val scalaLibTastyPaths = + new Directory(scalaLibClassesPath).deepFiles + .filter(_.`extension` == "tasty") + .map(_.normalize.path.stripPrefix(scalaLibClassesPath.toString + separator)) + .toList + +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", + "-d", s"out${separator}scala2-library-from-tasty-test-output.jar", + "-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) + s"scala${separator}Array.tasty", + s"scala${separator}Boolean.tasty", + s"scala${separator}Byte.tasty", + s"scala${separator}Char.tasty", + s"scala${separator}Double.tasty", + s"scala${separator}Float.tasty", + s"scala${separator}Int.tasty", + s"scala${separator}Long.tasty", + s"scala${separator}Short.tasty", + s"scala${separator}Unit.tasty", +)