diff --git a/.drone.yml b/.drone.yml index 839cbb9a1aae..35a4b6177b49 100644 --- a/.drone.yml +++ b/.drone.yml @@ -27,7 +27,7 @@ steps: - name: test pull: default - image: lampepfl/dotty:2019-10-17 + image: lampepfl/dotty:2020-01-09 depends_on: [ clone ] commands: - cp -R . /tmp/1/ && cd /tmp/1/ @@ -36,16 +36,16 @@ steps: - name: test_bootstrapped pull: default - image: lampepfl/dotty:2019-10-17 + image: lampepfl/dotty:2020-01-09 depends_on: [ clone ] commands: - cp -R . /tmp/2/ && cd /tmp/2/ - - ./project/scripts/sbt ";dotty-bootstrapped/compile ;dotty-bootstrapped/test ;dotty-staging/test ;sjsSandbox/run;sjsSandbox/test;sjsJUnitTests/test" + - ./project/scripts/sbt ";dotty-bootstrapped/compile ;dotty-bootstrapped/test ;dotty-staging/test ;sjsSandbox/run;sjsSandbox/test;sjsJUnitTests/test ;configureIDE" - ./project/scripts/bootstrapCmdTests - name: community_build pull: default - image: lampepfl/dotty:2019-10-17 + image: lampepfl/dotty:2020-01-09 depends_on: [ clone ] commands: - cp -R . /tmp/3/ && cd /tmp/3/ @@ -55,7 +55,7 @@ steps: - name: test_sbt pull: default - image: lampepfl/dotty:2019-10-17 + image: lampepfl/dotty:2020-01-09 depends_on: [ clone ] commands: - cp -R . /tmp/4/ && cd /tmp/4/ @@ -67,7 +67,7 @@ steps: - name: test_java11 pull: default - image: lampepfl/dotty:2019-10-17 + image: lampepfl/dotty:2020-01-09 depends_on: [ clone ] commands: - export PATH="/usr/lib/jvm/java-11-openjdk-amd64/bin:$PATH" @@ -80,7 +80,7 @@ steps: - name: documentation pull: default - image: lampepfl/dotty:2019-10-17 + image: lampepfl/dotty:2020-01-09 depends_on: - test - test_bootstrapped @@ -99,7 +99,7 @@ steps: - name: publish_nightly pull: default - image: lampepfl/dotty:2019-10-17 + image: lampepfl/dotty:2020-01-09 depends_on: - test - test_bootstrapped @@ -126,7 +126,7 @@ steps: - name: publish_release pull: default - image: lampepfl/dotty:2019-10-17 + image: lampepfl/dotty:2020-01-09 depends_on: - test - test_bootstrapped @@ -169,7 +169,7 @@ steps: - name: publish_sbt_release pull: default - image: lampepfl/dotty:2019-10-17 + image: lampepfl/dotty:2020-01-09 depends_on: - test - test_bootstrapped diff --git a/community-build/community-projects/scalap b/community-build/community-projects/scalap index fe6239e99c07..a20c669b8f26 160000 --- a/community-build/community-projects/scalap +++ b/community-build/community-projects/scalap @@ -1 +1 @@ -Subproject commit fe6239e99c07bf838e57fe0dc9930208a5486ad3 +Subproject commit a20c669b8f264a7b08cfccd875049420007deada diff --git a/community-build/community-projects/semanticdb b/community-build/community-projects/semanticdb index 05b8001beade..168b1f6881dd 160000 --- a/community-build/community-projects/semanticdb +++ b/community-build/community-projects/semanticdb @@ -1 +1 @@ -Subproject commit 05b8001beade3492f7eb8ab9425dd7454f66fe4b +Subproject commit 168b1f6881dd2f79025ae3db61bf7f56120c369b diff --git a/community-build/community-projects/stdLib213 b/community-build/community-projects/stdLib213 index ec4624b48262..1886950613d8 160000 --- a/community-build/community-projects/stdLib213 +++ b/community-build/community-projects/stdLib213 @@ -1 +1 @@ -Subproject commit ec4624b482626020e154d2e6161ef5f5f38f166c +Subproject commit 1886950613d85af824435b2c072e9eedb12d6851 diff --git a/community-build/project/build.properties b/community-build/project/build.properties deleted file mode 100644 index 72f902892a13..000000000000 --- a/community-build/project/build.properties +++ /dev/null @@ -1 +0,0 @@ -sbt.version=1.2.7 diff --git a/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala b/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala index 1c2c8aba7321..d03ebc905e15 100644 --- a/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala +++ b/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala @@ -100,7 +100,7 @@ final case class SbtCommunityProject(project: String, sbtTestCommand: String, case Some(ivyHome) => List(s"-Dsbt.ivy.home=$ivyHome") case _ => Nil extraSbtArgs ++ sbtProps ++ List( - "-sbt-version", "1.2.7", + "-sbt-version", "1.3.6", s"--addPluginSbtFile=$sbtPluginFilePath") object projects diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 8e5cf657a624..246a7331106b 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -7,6 +7,7 @@ import org.junit.Assert._ import org.junit.Assume._ import org.junit.experimental.categories.Category +import java.io.File import java.nio.file._ import java.util.stream.{ Stream => JStream } import scala.collection.JavaConverters._ @@ -197,24 +198,26 @@ class CompilationTests extends ParallelTesting { */ @Test def tastyBootstrap: Unit = { implicit val testGroup: TestGroup = TestGroup("tastyBootstrap/tests") + val libGroup = TestGroup("tastyBootstrap/lib") + val tastyCoreGroup = TestGroup("tastyBootstrap/tastyCore") val dotty1Group = TestGroup("tastyBootstrap/dotty1") val dotty2Group = TestGroup("tastyBootstrap/dotty2") - val libGroup = TestGroup("tastyBootstrap/lib") // Make sure that the directory is clean dotty.tools.io.Directory(defaultOutputDir + "tastyBootstrap").deleteRecursively() - val sep = java.io.File.pathSeparator - val opt = TestFlags( - // compile with bootstrapped library on cp: - defaultOutputDir + libGroup + "/src/" + sep + - // as well as bootstrapped compiler: - defaultOutputDir + dotty1Group + "/dotty/" + sep + - // and the other compiler dependenies: - Properties.compilerInterface + sep + Properties.scalaLibrary + sep + Properties.scalaAsm + sep + - Properties.dottyInterfaces + sep + Properties.tastyCore + sep + Properties.jlineTerminal + sep + - Properties.jlineReader, + List( + // compile with bootstrapped library on cp: + defaultOutputDir + libGroup + "/lib/", + // and bootstrapped tasty-core: + defaultOutputDir + tastyCoreGroup + "/tastyCore/", + // as well as bootstrapped compiler: + defaultOutputDir + dotty1Group + "/dotty1/", + // and the other compiler dependencies: + Properties.compilerInterface, Properties.scalaLibrary, Properties.scalaAsm, + Properties.dottyInterfaces, Properties.jlineTerminal, Properties.jlineReader, + ).mkString(File.pathSeparator), Array("-Ycheck-reentrant", "-Yemit-tasty-in-class") ) @@ -222,20 +225,23 @@ class CompilationTests extends ParallelTesting { val librarySources = libraryDirs.flatMap(sources(_)) val lib = - compileList("src", librarySources, + compileList("lib", librarySources, defaultOptions.and("-Ycheck-reentrant", "-Yerased-terms", // support declaration of scala.compiletime.erasedValue // "-strict", // TODO: re-enable once we allow : @unchecked in pattern definitions. Right now, lots of narrowing pattern definitions fail. "-priorityclasspath", defaultOutputDir))(libGroup) + val tastyCoreSources = sources(Paths.get("tasty/src")) + val tastyCore = compileList("tastyCore", tastyCoreSources, opt)(tastyCoreGroup) + val compilerSources = sources(Paths.get("compiler/src")) val compilerManagedSources = sources(Properties.dottyCompilerManagedSources) - val dotty1 = compileList("dotty", compilerSources ++ compilerManagedSources, opt)(dotty1Group) - val dotty2 = compileList("dotty", compilerSources ++ compilerManagedSources, opt)(dotty2Group) + val dotty1 = compileList("dotty1", compilerSources ++ compilerManagedSources, opt)(dotty1Group) + val dotty2 = compileList("dotty2", compilerSources ++ compilerManagedSources, opt)(dotty2Group) val tests = { - lib.keepOutput :: dotty1.keepOutput :: aggregateTests( + lib.keepOutput :: tastyCore.keepOutput :: dotty1.keepOutput :: aggregateTests( dotty2, compileShallowFilesInDir("compiler/src/dotty/tools", opt), compileShallowFilesInDir("compiler/src/dotty/tools/dotc", opt), @@ -255,9 +261,10 @@ class CompilationTests extends ParallelTesting { }.map(_.checkCompile()) def assertExists(path: String) = assertTrue(Files.exists(Paths.get(path))) - assertExists(s"out/$dotty1Group/dotty/") - assertExists(s"out/$dotty2Group/dotty/") - assertExists(s"out/$libGroup/src/") + assertExists(s"out/$libGroup/lib/") + assertExists(s"out/$tastyCoreGroup/tastyCore/") + assertExists(s"out/$dotty1Group/dotty1/") + assertExists(s"out/$dotty2Group/dotty2/") compileList("idempotency", List("tests/idempotency/BootstrapChecker.scala", "tests/idempotency/IdempotencyCheck.scala"), defaultOptions).checkRuns() tests.foreach(_.delete()) diff --git a/project/Build.scala b/project/Build.scala index 43c8ea9b47c1..f73866848728 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -54,14 +54,18 @@ object MyScalaJSPlugin extends AutoPlugin { // Typecheck the Scala.js IR found on the classpath scalaJSLinkerConfig ~= (_.withCheckIR(true)), + + // Exclude all these projects from `configureIDE/launchIDE` since they + // take time to compile, print a bunch of warnings, and are rarely edited. + excludeFromIDE := true ) } object Build { - val referenceVersion = "0.21.0-RC1" + val referenceVersion = "0.22.0-bin-20200114-193f7de-NIGHTLY" val baseVersion = "0.22.0" - val baseSbtDottyVersion = "0.3.5" + val baseSbtDottyVersion = "0.4.0" // Versions used by the vscode extension to create a new project // This should be the latest published releases. @@ -192,6 +196,11 @@ object Build { state }, + // Turn off the sbt supershell because it can mangle the output of some tasks + // (see https://github.com/sbt/sbt/issues/5122, https://github.com/sbt/sbt/issues/5352) + // and in general I find it more distracting than helpful anyway. + useSuperShell := false, + // Credentials to release to Sonatype credentials ++= ( for { @@ -730,16 +739,18 @@ object Build { case Bootstrapped => `dotty-compiler-bootstrapped` } - // Settings shared between dotty-library and dotty-library-bootstrapped + // Settings shared between dotty-library, dotty-library-bootstrapped and dotty-library-bootstrappedJS lazy val dottyLibrarySettings = Seq( - // Needed so that the library sources are visible when `dotty.tools.dotc.core.Definitions#init` is called - scalacOptions in Compile ++= Seq("-sourcepath", (sourceDirectories in Compile).value.map(_.getAbsolutePath).distinct.mkString(File.pathSeparator)), + scalacOptions in Compile ++= Seq( + // Needed so that the library sources are visible when `dotty.tools.dotc.core.Definitions#init` is called + "-sourcepath", (sourceDirectories in Compile).value.map(_.getAbsolutePath).distinct.mkString(File.pathSeparator), + // support declaration of scala.compiletime.erasedValue + "-Yerased-terms" + ), ) lazy val `dotty-library` = project.in(file("library")).asDottyLibrary(NonBootstrapped) lazy val `dotty-library-bootstrapped`: Project = project.in(file("library")).asDottyLibrary(Bootstrapped) - // TODO: move -Yerased-terms to dottyLibrarySettings on reference compiler update - .settings(scalacOptions in Compile += "-Yerased-terms") // support declaration of scala.compiletime.erasedValue def dottyLibrary(implicit mode: Mode): Project = mode match { case NonBootstrapped => `dotty-library` @@ -761,7 +772,6 @@ object Build { settings( unmanagedSourceDirectories in Compile := (unmanagedSourceDirectories in (`dotty-library-bootstrapped`, Compile)).value, - scalacOptions += "-Yerased-terms", // support declaration of scala.compiletime.erasedValue ) lazy val tastyCoreSettings = Seq( @@ -1109,8 +1119,6 @@ object Build { version := "0.1.17-snapshot", // Keep in sync with package.json autoScalaLibrary := false, publishArtifact := false, - includeFilter in unmanagedSources := NothingFilter | "*.ts" | "**.json", - watchSources in Global ++= (unmanagedSources in Compile).value, resourceGenerators in Compile += Def.task { // Resources that will be copied when bootstrapping a new project val buildSbtFile = baseDirectory.value / "out" / "build.sbt" diff --git a/project/build.properties b/project/build.properties index 72f902892a13..00b48d978b25 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.2.7 +sbt.version=1.3.6 diff --git a/sbt-dotty/sbt-test/sbt-dotty/i7897/build.sbt b/sbt-dotty/sbt-test/sbt-dotty/i7897/build.sbt new file mode 100644 index 000000000000..0f1833c230ab --- /dev/null +++ b/sbt-dotty/sbt-test/sbt-dotty/i7897/build.sbt @@ -0,0 +1,5 @@ +scalaVersion := sys.props("plugin.scalaVersion") + +libraryDependencies += "ch.epfl.lamp" %% "dotty-staging" % scalaVersion.value + +fork := true diff --git a/sbt-dotty/sbt-test/sbt-dotty/i7897/changes/build-no-fork.sbt b/sbt-dotty/sbt-test/sbt-dotty/i7897/changes/build-no-fork.sbt new file mode 100644 index 000000000000..802dff0748fe --- /dev/null +++ b/sbt-dotty/sbt-test/sbt-dotty/i7897/changes/build-no-fork.sbt @@ -0,0 +1,5 @@ +scalaVersion := sys.props("plugin.scalaVersion") + +libraryDependencies += "ch.epfl.lamp" %% "dotty-staging" % scalaVersion.value + +fork := false diff --git a/sbt-dotty/sbt-test/source-dependencies/relative-source-error/project/plugins.sbt b/sbt-dotty/sbt-test/sbt-dotty/i7897/project/plugins.sbt similarity index 100% rename from sbt-dotty/sbt-test/source-dependencies/relative-source-error/project/plugins.sbt rename to sbt-dotty/sbt-test/sbt-dotty/i7897/project/plugins.sbt diff --git a/sbt-dotty/sbt-test/sbt-dotty/i7897/src/main/scala/hello/i7897.scala b/sbt-dotty/sbt-test/sbt-dotty/i7897/src/main/scala/hello/i7897.scala new file mode 100644 index 000000000000..eb4b5ac08be4 --- /dev/null +++ b/sbt-dotty/sbt-test/sbt-dotty/i7897/src/main/scala/hello/i7897.scala @@ -0,0 +1,14 @@ +import scala.quoted._, staging._ + +given Toolbox = Toolbox.make(getClass.getClassLoader) + +val f: Array[Int] => Int = run { + val stagedSum: Expr[Array[Int] => Int] = '{ (arr: Array[Int]) => 6 } + println(stagedSum.show) + stagedSum +} + +object Main { + def main(args: Array[String]): Unit = + f.apply(Array(1, 2, 3)) // Returns 6 +} diff --git a/sbt-dotty/sbt-test/sbt-dotty/i7897/test b/sbt-dotty/sbt-test/sbt-dotty/i7897/test new file mode 100644 index 000000000000..42d5b04677a8 --- /dev/null +++ b/sbt-dotty/sbt-test/sbt-dotty/i7897/test @@ -0,0 +1,4 @@ +> run +$ copy-file changes/build-no-fork.sbt build.sbt +> reload +> run diff --git a/sbt-dotty/sbt-test/source-dependencies/relative-source-error/changes/absolute.sbt b/sbt-dotty/sbt-test/source-dependencies/relative-source-error/changes/absolute.sbt deleted file mode 100644 index a5f2d007a58c..000000000000 --- a/sbt-dotty/sbt-test/source-dependencies/relative-source-error/changes/absolute.sbt +++ /dev/null @@ -1 +0,0 @@ -scalaSource in Compile := baseDirectory.value / "src" \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/relative-source-error/changes/relative.sbt b/sbt-dotty/sbt-test/source-dependencies/relative-source-error/changes/relative.sbt deleted file mode 100644 index 8e898fe02829..000000000000 --- a/sbt-dotty/sbt-test/source-dependencies/relative-source-error/changes/relative.sbt +++ /dev/null @@ -1 +0,0 @@ -scalaSource in Compile := file("src") \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/relative-source-error/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/relative-source-error/project/DottyInjectedPlugin.scala deleted file mode 100644 index 6a77cb33121e..000000000000 --- a/sbt-dotty/sbt-test/source-dependencies/relative-source-error/project/DottyInjectedPlugin.scala +++ /dev/null @@ -1,12 +0,0 @@ -import sbt._ -import Keys._ - -object DottyInjectedPlugin extends AutoPlugin { - override def requires = plugins.JvmPlugin - override def trigger = allRequirements - - override val projectSettings = Seq( - scalaVersion := sys.props("plugin.scalaVersion"), - scalacOptions += "-language:Scala2Compat" - ) -} diff --git a/sbt-dotty/sbt-test/source-dependencies/relative-source-error/src/A.scala b/sbt-dotty/sbt-test/source-dependencies/relative-source-error/src/A.scala deleted file mode 100644 index 528ffce71c5f..000000000000 --- a/sbt-dotty/sbt-test/source-dependencies/relative-source-error/src/A.scala +++ /dev/null @@ -1 +0,0 @@ -object A \ No newline at end of file diff --git a/sbt-dotty/sbt-test/source-dependencies/relative-source-error/test b/sbt-dotty/sbt-test/source-dependencies/relative-source-error/test deleted file mode 100644 index fb8e9dce835f..000000000000 --- a/sbt-dotty/sbt-test/source-dependencies/relative-source-error/test +++ /dev/null @@ -1,7 +0,0 @@ -$ copy-file changes/relative.sbt build.sbt -> reload --> compile - -$ copy-file changes/absolute.sbt build.sbt -> reload -> compile diff --git a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala index 2b12150520a2..3af93b4d6bd2 100644 --- a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala +++ b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala @@ -154,7 +154,7 @@ object DottyPlugin extends AutoPlugin { override val globalSettings: Seq[Def.Setting[_]] = Seq( onLoad in Global := onLoad.in(Global).value.andThen { state => - val requiredVersion = ">=1.2.7" + val requiredVersion = ">=1.3.6" val sbtV = sbtVersion.value if (!VersionNumber(sbtV).matchesSemVer(SemanticSelector(requiredVersion))) @@ -210,41 +210,42 @@ object DottyPlugin extends AutoPlugin { scalaBinaryVersion.value }, - // Ideally, we should have: + // We want: // // 1. Nothing but the Java standard library on the _JVM_ bootclasspath // (starting with Java 9 we cannot inspect it so we don't have a choice) // - // 2. scala-library, dotty-library, dotty-compiler, dotty-doc on the _JVM_ - // classpath, because we need all of those to actually run the compiler - // and the doc tool. + // 2. scala-library, dotty-library, dotty-compiler and its dependencies on the _JVM_ + // classpath, because we need all of those to actually run the compiler. // NOTE: All of those should have the *same version* (equal to scalaVersion // for everything but scala-library). + // (Complication: because dottydoc is a separate artifact with its own dependencies, + // running it requires putting extra dependencies on the _JVM_ classpath) // - // 3. scala-library, dotty-library on the _compiler_ bootclasspath because - // user code should always have access to the symbols from these jars but - // should not be able to shadow them (the compiler bootclasspath has - // higher priority than the compiler classpath). + // 3. scala-library, dotty-library on the _compiler_ bootclasspath or + // classpath (the only difference between them is that the compiler + // bootclasspath has higher priority, but that should never + // make a difference in a sane environment). // NOTE: the versions of {scala,dotty}-library used here do not necessarily // match the one used in 2. because a dependency of the current project might - // require more recent versions, this is OK. + // require a more recent standard library version, this is OK + // TODO: ... but if macros are used we might be forced to use the same + // versions in the JVM and compiler classpaths to avoid problems, this + // needs to be investigated. // // 4. every other dependency of the user project on the _compiler_ // classpath. // - // Unfortunately, zinc assumes that the compiler bootclasspath is only - // made of one jar (scala-library), so to make this work we'll need to - // either change sbt's bootclasspath handling or wait until the - // dotty-library jar and scala-library jars are merged into one jar. - // Furthermore, zinc will put on the compiler bootclasspath the + // By default, zinc will put on the compiler bootclasspath the // scala-library used on the JVM classpath, even if the current project // transitively depends on a newer scala-library (this works because Scala // 2 guarantees forward- and backward- binary compatibility, but we don't // necessarily want to keep doing that in Scala 3). // So for the moment, let's just put nothing at all on the compiler - // bootclasspath, and instead have scala-library and dotty-library on the - // compiler classpath. This means that user code could shadow symbols - // from these jars but we can live with that for now. + // bootclasspath, and instead let sbt dependency management choose which + // scala-library and dotty-library to put on the compiler classpath. + // Maybe eventually we should just remove the compiler bootclasspath since + // it's a source of complication with only dubious benefits. // sbt crazy scoping rules mean that when we override `classpathOptions` // below we also override `classpathOptions in console` which is normally @@ -404,7 +405,7 @@ object DottyPlugin extends AutoPlugin { /** Create a scalaInstance task that uses Dotty based on `moduleName`. */ def dottyScalaInstanceTask(moduleName: String): Initialize[Task[ScalaInstance]] = Def.task { - val ivyConfig0 = mkIvyConfiguration.value + val ivyConfig0 = Classpaths.mkIvyConfiguration.value // When compiling non-bootstrapped projects in the build of Dotty itself, // dependency resolution might pick a local project which is not what we // want. We avoid this by dropping the inter-project resolver. @@ -436,37 +437,22 @@ object DottyPlugin extends AutoPlugin { ) } - // Copy-pasted from sbt until we upgrade to a version of sbt - // with https://github.com/sbt/sbt/pull/5271 in. - def mkIvyConfiguration: Initialize[Task[InlineIvyConfiguration]] = - Def.task { - val (rs, other) = (fullResolvers.value.toVector, otherResolvers.value.toVector) - val s = streams.value - Classpaths.warnResolversConflict(rs ++: other, s.log) - InlineIvyConfiguration() - .withPaths(ivyPaths.value) - .withResolvers(rs) - .withOtherResolvers(other) - .withModuleConfigurations(moduleConfigurations.value.toVector) - .withLock(Defaults.lock(appConfiguration.value)) - .withChecksums((checksums in update).value.toVector) - .withResolutionCacheDir(crossTarget.value / "resolution-cache") - .withUpdateOptions(updateOptions.value) - .withLog(s.log) - } - + // Adapted from private mkScalaInstance in sbt def makeScalaInstance( state: State, dottyVersion: String, scalaLibrary: File, dottyLibrary: File, compiler: File, all: Seq[File] ): ScalaInstance = { - val loader = state.classLoaderCache(all.toList) - val loaderLibraryOnly = state.classLoaderCache(List(dottyLibrary, scalaLibrary)) + val libraryLoader = state.classLoaderCache(List(dottyLibrary, scalaLibrary)) + class DottyLoader + extends URLClassLoader(all.map(_.toURI.toURL).toArray, libraryLoader) + val fullLoader = state.classLoaderCache.cachedCustomClassloader( + all.toList, + () => new DottyLoader + ) new ScalaInstance( dottyVersion, - loader, - loaderLibraryOnly, - scalaLibrary, // Should be a Seq also containing dottyLibrary but zinc - // doesn't support this, see comment above our redefinition - // of `classpathOption` + fullLoader, + libraryLoader, + Array(dottyLibrary, scalaLibrary), compiler, all.toArray, None) diff --git a/staging/src/scala/quoted/staging/QuoteDriver.scala b/staging/src/scala/quoted/staging/QuoteDriver.scala index 68441e61cf84..fe4410bafeb6 100644 --- a/staging/src/scala/quoted/staging/QuoteDriver.scala +++ b/staging/src/scala/quoted/staging/QuoteDriver.scala @@ -11,6 +11,9 @@ import dotty.tools.dotc.reporting._ import scala.quoted._ import scala.quoted.staging.Toolbox import java.net.URLClassLoader +import java.nio.file.Paths +import java.io.File +import scala.annotation.tailrec /** Driver to compile quoted code * @@ -53,7 +56,7 @@ private class QuoteDriver(appClassloader: ClassLoader) extends Driver { override def initCtx: Context = { val ictx = contextBase.initialCtx - ictx.settings.classpath.update(getCurrentClasspath(appClassloader))(ictx) + ictx.settings.classpath.update(classpathFromClassloader(appClassloader))(ictx) ictx } @@ -64,17 +67,42 @@ private class QuoteDriver(appClassloader: ClassLoader) extends Driver { ctx.setReporter(new ThrowingReporter(ctx.reporter)) } - private def getCurrentClasspath(cl: ClassLoader): String = { - val classpath0 = System.getProperty("java.class.path") - cl match { - case cl: URLClassLoader => - // Loads the classes loaded by this class loader - // When executing `run` or `test` in sbt the classpath is not in the property java.class.path - import java.nio.file.Paths - val newClasspath = cl.getURLs.map(url => Paths.get(url.toURI).toString) - newClasspath.mkString("", java.io.File.pathSeparator, if (classpath0 == "") "" else java.io.File.pathSeparator + classpath0) - case _ => classpath0 + /** Attempt to recreate a classpath from a classloader. + * + * BEWARE: with exotic enough classloaders, this may not work at all or do + * the wrong thing. + */ + private def classpathFromClassloader(cl: ClassLoader): String = { + val classpathBuff = List.newBuilder[String] + def collectClassLoaderPaths(cl: ClassLoader): Unit = { + if (cl != null) { + cl match { + case cl: URLClassLoader => + // This is wrong if we're in a subclass of URLClassLoader + // that filters loading classes from its parent ¯\_(ツ)_/¯ + collectClassLoaderPaths(cl.getParent) + // Parent classloaders are searched before their child, so the part of + // the classpath coming from the child is added at the _end_ of the + // classpath. + classpathBuff ++= + cl.getURLs.iterator.map(url => Paths.get(url.toURI).toAbsolutePath.toString) + case _ => + // HACK: We can't just collect the classpath from arbitrary parent + // classloaders since the current classloader might intentionally + // filter loading classes from its parent (for example + // BootFilteredLoader in the sbt launcher does this and we really + // don't want to include the scala-library that sbt depends on + // here), but we do need to look at the parent of the REPL + // classloader, so we special case it. We can't do this using a type + // test since the REPL classloader class itself is normally loaded + // with a different classloader. + if (cl.getClass.getName == classOf[AbstractFileClassLoader].getName) + collectClassLoaderPaths(cl.getParent) + } + } } + collectClassLoaderPaths(cl) + classpathBuff.result().mkString(java.io.File.pathSeparator) } } diff --git a/tests/idempotency/BootstrapChecker.scala b/tests/idempotency/BootstrapChecker.scala index 7c88ed597298..cfd868060409 100644 --- a/tests/idempotency/BootstrapChecker.scala +++ b/tests/idempotency/BootstrapChecker.scala @@ -1,5 +1,5 @@ object Test { def main(args: Array[String]): Unit = - IdempotencyCheck.checkIdempotency("out/tastyBootstrap/dotty1", "out/tastyBootstrap/dotty2") + IdempotencyCheck.checkIdempotency("out/tastyBootstrap/dotty1/dotty1", "out/tastyBootstrap/dotty2/dotty2") }