From d8d2b02e7eac1397a50a5a2bf433ddc50b0329b7 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 22 Jan 2024 16:29:46 +0100 Subject: [PATCH 1/9] Use the ordinary compiler classpath for scala-library No longer pass `-bootclasspath /path/to/scala-library.jar` to the Scala compiler, put the library on the ordinary classpath. --- main/src/main/scala/sbt/Defaults.scala | 4 ++-- main/src/main/scala/sbt/internal/Load.scala | 2 +- .../sbt-test/compiler-project/no-bootclasspath/build.sbt | 9 +++++++++ .../src/sbt-test/compiler-project/no-bootclasspath/test | 4 ++++ .../scala/sbt/internal/inc/ZincComponentCompiler.scala | 6 +++++- 5 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 sbt-app/src/sbt-test/compiler-project/no-bootclasspath/build.sbt create mode 100644 sbt-app/src/sbt-test/compiler-project/no-bootclasspath/test diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index f3cd01835..e6303a825 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -730,14 +730,14 @@ object Defaults extends BuildCommon { consoleProject / scalaCompilerBridgeSource := ZincLmUtil.getDefaultBridgeSourceModule( appConfiguration.value.provider.scalaProvider.version ), + classpathOptions := ClasspathOptionsUtil.noboot(scalaVersion.value), + console / classpathOptions := ClasspathOptionsUtil.replNoboot(scalaVersion.value), ) // must be a val: duplication detected by object identity private[this] lazy val compileBaseGlobal: Seq[Setting[_]] = globalDefaults( Seq( auxiliaryClassFiles :== Nil, incOptions := IncOptions.of(), - classpathOptions :== ClasspathOptionsUtil.boot, - console / classpathOptions :== ClasspathOptionsUtil.repl, compileOrder :== CompileOrder.Mixed, javacOptions :== Nil, scalacOptions :== Nil, diff --git a/main/src/main/scala/sbt/internal/Load.scala b/main/src/main/scala/sbt/internal/Load.scala index b00e0a911..431c617f7 100755 --- a/main/src/main/scala/sbt/internal/Load.scala +++ b/main/src/main/scala/sbt/internal/Load.scala @@ -79,7 +79,7 @@ private[sbt] object Load { val dependencyResolution = IvyDependencyResolution(ivyConfiguration) val si = ScalaInstance(scalaProvider.version, scalaProvider.launcher) val zincDir = BuildPaths.getZincDirectory(state, globalBase) - val classpathOptions = ClasspathOptionsUtil.boot + val classpathOptions = ClasspathOptionsUtil.noboot(si.version) val scalac = ZincLmUtil.scalaCompiler( scalaInstance = si, classpathOptions = classpathOptions, diff --git a/sbt-app/src/sbt-test/compiler-project/no-bootclasspath/build.sbt b/sbt-app/src/sbt-test/compiler-project/no-bootclasspath/build.sbt new file mode 100644 index 000000000..edd870753 --- /dev/null +++ b/sbt-app/src/sbt-test/compiler-project/no-bootclasspath/build.sbt @@ -0,0 +1,9 @@ +TaskKey[Unit]("check212") := checkCp(true) +TaskKey[Unit]("check213") := checkCp(false) + +def checkCp(auto: Boolean) = Def.task { + val opts = compilers.value.scalac.classpathOptions + assert(opts.autoBoot == auto, opts) + assert(opts.filterLibrary == auto, opts) + () +} diff --git a/sbt-app/src/sbt-test/compiler-project/no-bootclasspath/test b/sbt-app/src/sbt-test/compiler-project/no-bootclasspath/test new file mode 100644 index 000000000..a62a34698 --- /dev/null +++ b/sbt-app/src/sbt-test/compiler-project/no-bootclasspath/test @@ -0,0 +1,4 @@ +> set scalaVersion := "2.13.12" +> check213 +> set scalaVersion := "2.12.18" +> check212 diff --git a/zinc-lm-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/zinc-lm-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index 20a649275..05a9ea6f1 100644 --- a/zinc-lm-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/zinc-lm-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -57,7 +57,11 @@ private[sbt] object ZincComponentCompiler { scalaInstance: XScalaInstance, logger: Logger, ): File = lock.synchronized { - val raw = new RawCompiler(scalaInstance, ClasspathOptionsUtil.auto, logger) + val raw = new RawCompiler( + scalaInstance, + ClasspathOptionsUtil.autoNoboot(scalaInstance.version), + logger + ) val zinc = new ZincComponentCompiler(raw, manager, dependencyResolution, bridgeSources, logger) logger.debug(f0(s"Getting $bridgeSources for Scala ${scalaInstance.version}")) From 893997d1b60504cbaa1b4e481dd30b9684c09aac Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 22 Jan 2024 16:30:20 +0100 Subject: [PATCH 2/9] Update scala libraries according to dependency graph There are a couple of settings / configs that affect this, summary below. The change in this PR seems to be the most narrow. `scalaModuleInfo.value.overrideScalaVersion` in sbt - affects how sbt to sets coursier's `forceScalaVersion` (see below) - used by librarymanagement.ivy. If true, add a OverrideScalaMediator See sbt/sbt#2634. Probably not relevant when using coursier. `autoScalaLibrary` setting in sbt - automatically add `scala-library` (or `scala3-library`) as a project dependency - also used for `forceScalaVersion` (see below) `CoursierConfiguration.autoScalaLibrary` - if `true` then Coursier `ResolutionParams.forceScalaVersion` is set to to `true` - initialized by sbt to `autoScalaLibrary.value && !ScalaArtifacts.isScala3(sv) && !Classpaths.isScala213(sv) && // added in this commit scalaModuleInfo.forall(_.overrideScalaVersion)` coursier `ResolutionParams.forceScalaVersion` - if true, `scala-library` / `scala-reflect` / `scala-compiler` / `scalap` are forced to the scala version, not actually resolved - for Scala 3, the `scala3-library` and `scala3-compiler` versions are forced --- main/src/main/scala/sbt/Defaults.scala | 2 ++ main/src/main/scala/sbt/coursierint/LMCoursier.scala | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index e6303a825..00aae7174 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -3934,6 +3934,8 @@ object Classpaths { def deliverPattern(outputPath: File): String = (outputPath / "[artifact]-[revision](-[classifier]).[ext]").absolutePath + private[sbt] def isScala213(sv: String) = sv.startsWith("2.13.") + private[sbt] def isScala2Scala3Sandwich(sbv1: String, sbv2: String): Boolean = { def compare(a: String, b: String): Boolean = a == "2.13" && (b.startsWith("0.") || b.startsWith("3")) diff --git a/main/src/main/scala/sbt/coursierint/LMCoursier.scala b/main/src/main/scala/sbt/coursierint/LMCoursier.scala index 865fbf899..8d795072a 100644 --- a/main/src/main/scala/sbt/coursierint/LMCoursier.scala +++ b/main/src/main/scala/sbt/coursierint/LMCoursier.scala @@ -212,7 +212,7 @@ object LMCoursier { scalaOrganization.value, sv, scalaBinaryVersion.value, - autoScalaLibrary.value && !ScalaArtifacts.isScala3(sv), + autoScalaLibrary.value && !ScalaArtifacts.isScala3(sv) && !Classpaths.isScala213(sv), scalaModuleInfo.value, allExcludeDependencies.value, CoursierInputsTasks.credentialsTask.value, @@ -240,7 +240,7 @@ object LMCoursier { scalaOrganization.value, sv, scalaBinaryVersion.value, - autoScalaLibrary.value && !ScalaArtifacts.isScala3(sv), + autoScalaLibrary.value && !ScalaArtifacts.isScala3(sv) && !Classpaths.isScala213(sv), scalaModuleInfo.value, allExcludeDependencies.value, CoursierInputsTasks.credentialsTask.value, @@ -268,7 +268,7 @@ object LMCoursier { scalaOrganization.value, sv, scalaBinaryVersion.value, - autoScalaLibrary.value && !ScalaArtifacts.isScala3(sv), + autoScalaLibrary.value && !ScalaArtifacts.isScala3(sv) && !Classpaths.isScala213(sv), scalaModuleInfo.value, allExcludeDependencies.value, CoursierInputsTasks.credentialsTask.value, @@ -296,7 +296,7 @@ object LMCoursier { scalaOrganization.value, sv, scalaBinaryVersion.value, - autoScalaLibrary.value && !ScalaArtifacts.isScala3(sv), + autoScalaLibrary.value && !ScalaArtifacts.isScala3(sv) && !Classpaths.isScala213(sv), scalaModuleInfo.value, allExcludeDependencies.value, CoursierInputsTasks.credentialsTask.value, From 35bc07bd9ed9a6512189e2287c08ef23335c285d Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 24 Oct 2023 17:29:14 +0200 Subject: [PATCH 3/9] Use scala library from classpath in sbt run class loader --- .../scala/sbt/internal/ClassLoaders.scala | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/main/src/main/scala/sbt/internal/ClassLoaders.scala b/main/src/main/scala/sbt/internal/ClassLoaders.scala index e54ebfa0b..a1d209510 100644 --- a/main/src/main/scala/sbt/internal/ClassLoaders.scala +++ b/main/src/main/scala/sbt/internal/ClassLoaders.scala @@ -12,7 +12,6 @@ package internal import java.io.File import java.net.URL import java.nio.file.Path - import sbt.ClassLoaderLayeringStrategy._ import sbt.Keys._ import sbt.SlashSyntax0._ @@ -22,10 +21,12 @@ import sbt.internal.inc.classpath.ClasspathUtil import sbt.internal.util.Attributed import sbt.internal.util.Attributed.data import sbt.io.IO +import sbt.librarymanagement.ScalaArtifacts import sbt.nio.FileStamp import sbt.nio.FileStamp.LastModified import sbt.nio.Keys._ import sbt.util.Logger +import xsbti.ArtifactInfo private[sbt] object ClassLoaders { private implicit class SeqFileOps(val files: Seq[File]) extends AnyVal { @@ -154,14 +155,24 @@ private[sbt] object ClassLoaders { case _: AllLibraryJars => true case _ => false } + val cpFiles = fullCP.map(_._1) val scalaLibraryLayer = { + val jars = + if (ScalaArtifacts.isScala3(si.version) || Classpaths.isScala213(si.version)) + cpFiles + .filter(f => { + val name = f.getName + name.contains(ArtifactInfo.ScalaLibraryID) || si.libraryJars + .exists(_.getName == name) + }) + .toArray + else si.libraryJars cache.apply( - si.libraryJars.map(j => j -> IO.getModifiedTimeOrZero(j)).toList, + jars.map(j => j -> IO.getModifiedTimeOrZero(j)).toList, interfaceLoader, - () => new ScalaLibraryClassLoader(si.libraryJars.map(_.toURI.toURL), interfaceLoader) + () => new ScalaLibraryClassLoader(jars.map(_.toURI.toURL), interfaceLoader) ) } - val cpFiles = fullCP.map(_._1) val allDependencies = cpFiles.filter(allDependenciesSet) def isReflectJar(f: File): Boolean = From 4c74358707477d105bf8d4d4452e2b7971b73ba7 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 12 Jan 2024 21:16:31 +0100 Subject: [PATCH 4/9] Fail the build if 2.13 scalaVersion < scala artifact on classpath When expanding a macro compiled against a new Scala library, the runtime classpath of the compiler should not contain an older library. Otherwise a NoSuchMethodException can occur. A similar issue is present when running the Scala repl through sbt. An input line compiled against a new library could fail to run if the repl's runtime classpath is on an old version. --- main/src/main/scala/sbt/Defaults.scala | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 00aae7174..c9b00f748 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -1150,6 +1150,23 @@ object Defaults extends BuildCommon { .configuration(Configurations.ScalaTool) .getOrElse(sys.error(noToolConfiguration(managedScalaInstance.value))) + if (Classpaths.isScala213(sv)) { + for { + compileReport <- fullReport.configuration(Configurations.Compile) + libName <- ScalaArtifacts.Artifacts + } { + for (lib <- compileReport.modules.find(_.module.name == libName)) { + val libVer = lib.module.revision + if (VersionNumber(sv).matchesSemVer(SemanticSelector(s"<$libVer"))) + sys.error( + s"""`${name.value}/scalaVersion` needs to be upgraded to $libVer. To support backwards-only + |binary compatibility (SIP-51), the Scala compiler cannot be older than $libName on the + |dependency classpath. See `${name.value}/evicted` why $libName was upgraded from $sv to $libVer. + |""".stripMargin + ) + } + } + } def file(id: String): File = { val files = for { m <- toolReport.modules if m.module.name.startsWith(id) From 951d1c4ae4477c0f5fa94786c8474011e2977858 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 22 Jan 2024 16:44:09 +0100 Subject: [PATCH 5/9] Add new `csrSameVersions` setting, use it for Scala artifacts The `csrSameVersions` setting can be used to keep dependencies at the same version. By default it's used for Scala artifacts. They need to be kept at the same version because the compiler / reflect are built with cross-artifact inlining enabled. `csrSameVersions := Seq(Set(scala-library, scala-reflect, scala-compiler, scalap))` Users can make use of the new setting in the following way: - `csrSameVersions += Set[InclExclRule]("com.corp" % "lib", "com.corp" % "lub")` - `csrSameVersions += Set[InclExclRule]("com.corp" % "lib-family-*")` --- main/src/main/scala/sbt/Defaults.scala | 3 + main/src/main/scala/sbt/Keys.scala | 1 + .../scala/sbt/coursierint/LMCoursier.scala | 59 +++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index c9b00f748..ed83474dc 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -271,6 +271,9 @@ object Defaults extends BuildCommon { csrLogger := LMCoursier.coursierLoggerTask.value, csrMavenProfiles :== Set.empty, csrReconciliations :== LMCoursier.relaxedForAllModules, + csrSameVersions := Seq( + ScalaArtifacts.Artifacts.map(a => InclExclRule(scalaOrganization.value, a)).toSet + ) ) /** Core non-plugin settings for sbt builds. These *must* be on every build or the sbt engine will fail to run at all. */ diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index 4d19d798d..69073fc16 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -452,6 +452,7 @@ object Keys { val csrExtraCredentials = taskKey[Seq[lmcoursier.credentials.Credentials]]("") val csrPublications = taskKey[Seq[(lmcoursier.definitions.Configuration, lmcoursier.definitions.Publication)]]("") val csrReconciliations = settingKey[Seq[(ModuleMatchers, Reconciliation)]]("Strategy to reconcile version conflicts.") + val csrSameVersions = settingKey[Seq[Set[InclExclRule]]]("Modules to keep at the same version.") val internalConfigurationMap = settingKey[Configuration => Configuration]("Maps configurations to the actual configuration used to define the classpath.").withRank(CSetting) val classpathConfiguration = taskKey[Configuration]("The configuration used to define the classpath.").withRank(CTask) diff --git a/main/src/main/scala/sbt/coursierint/LMCoursier.scala b/main/src/main/scala/sbt/coursierint/LMCoursier.scala index 8d795072a..84ed5339d 100644 --- a/main/src/main/scala/sbt/coursierint/LMCoursier.scala +++ b/main/src/main/scala/sbt/coursierint/LMCoursier.scala @@ -74,6 +74,7 @@ object LMCoursier { def relaxedForAllModules: Seq[(ModuleMatchers, Reconciliation)] = Vector((ModuleMatchers.all, Reconciliation.Relaxed)) + // For binary compatibility / MiMa def coursierConfiguration( rs: Seq[Resolver], interProjectDependencies: Seq[CProject], @@ -119,6 +120,58 @@ object LMCoursier { strict, depsOverrides, None, + Nil, + log + ) + + // For binary compatibility / MiMa + def coursierConfiguration( + rs: Seq[Resolver], + interProjectDependencies: Seq[CProject], + extraProjects: Seq[CProject], + fallbackDeps: Seq[FallbackDependency], + appConfig: AppConfiguration, + classifiers: Option[Seq[Classifier]], + profiles: Set[String], + scalaOrg: String, + scalaVer: String, + scalaBinaryVer: String, + autoScalaLib: Boolean, + scalaModInfo: Option[ScalaModuleInfo], + excludeDeps: Seq[InclExclRule], + credentials: Seq[Credentials], + createLogger: Option[CacheLogger], + cacheDirectory: File, + reconciliation: Seq[(ModuleMatchers, Reconciliation)], + ivyHome: Option[File], + strict: Option[CStrict], + depsOverrides: Seq[ModuleID], + updateConfig: Option[UpdateConfiguration], + log: Logger + ): CoursierConfiguration = + coursierConfiguration( + rs, + interProjectDependencies, + extraProjects, + fallbackDeps, + appConfig, + classifiers, + profiles, + scalaOrg, + scalaVer, + scalaBinaryVer, + autoScalaLib, + scalaModInfo, + excludeDeps, + credentials, + createLogger, + cacheDirectory, + reconciliation, + ivyHome, + strict, + depsOverrides, + updateConfig, + Nil, log ) @@ -144,6 +197,7 @@ object LMCoursier { strict: Option[CStrict], depsOverrides: Seq[ModuleID], updateConfig: Option[UpdateConfiguration], + sameVersions: Seq[Set[InclExclRule]], log: Logger ): CoursierConfiguration = { val coursierExcludeDeps = Inputs @@ -197,6 +251,7 @@ object LMCoursier { .withStrict(strict) .withForceVersions(userForceVersions.toVector) .withMissingOk(missingOk) + .withSameVersions(sameVersions) } def coursierConfigurationTask: Def.Initialize[Task[CoursierConfiguration]] = Def.task { @@ -223,6 +278,7 @@ object LMCoursier { CoursierInputsTasks.strictTask.value, dependencyOverrides.value, Some(updateConfiguration.value), + csrSameVersions.value, streams.value.log ) } @@ -251,6 +307,7 @@ object LMCoursier { CoursierInputsTasks.strictTask.value, dependencyOverrides.value, Some(updateConfiguration.value), + csrSameVersions.value, streams.value.log ) } @@ -279,6 +336,7 @@ object LMCoursier { CoursierInputsTasks.strictTask.value, dependencyOverrides.value, Some(updateConfiguration.value), + csrSameVersions.value, streams.value.log ) } @@ -307,6 +365,7 @@ object LMCoursier { CoursierInputsTasks.strictTask.value, dependencyOverrides.value, Some(updateConfiguration.value), + csrSameVersions.value, streams.value.log ) } From b9375f5e6b1b5c55b67b7d5987efe25bca3df699 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 22 Jan 2024 13:41:51 +0100 Subject: [PATCH 6/9] Update scala-library in scala-tool configuration for Scala 3 When a macro was compiled against a new scala-library (say 2.13.15), the runtime classpath of the Scala compiler should not contain an older scala-library. Otherwise the macro can cause a NoSuchMethodException during expansion. This commit updates scala-library in the scalaInstance to the version on the projects dependency classpath. --- main/src/main/scala/sbt/Defaults.scala | 27 +++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index ed83474dc..133e46434 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -1149,9 +1149,29 @@ object Defaults extends BuildCommon { val sv = scalaVersion.value val fullReport = update.value - val toolReport = fullReport - .configuration(Configurations.ScalaTool) - .getOrElse(sys.error(noToolConfiguration(managedScalaInstance.value))) + // For Scala 3, update scala-library.jar in `scala-tool` and `scala-doc-tool` in case a newer version + // is present in the `compile` configuration. This is needed once forwards binary compatibility is dropped + // to avoid NoSuchMethod exceptions when expanding macros. + def updateLibraryToCompileConfiguration(report: ConfigurationReport) = + if (!ScalaArtifacts.isScala3(sv)) report + else + (for { + compileConf <- fullReport.configuration(Configurations.Compile) + compileLibMod <- compileConf.modules.find(_.module.name == ScalaArtifacts.LibraryID) + reportLibMod <- report.modules.find(_.module.name == ScalaArtifacts.LibraryID) + if VersionNumber(reportLibMod.module.revision) + .matchesSemVer(SemanticSelector(s"<${compileLibMod.module.revision}")) + } yield { + val newMods = report.modules + .filterNot(_.module.name == ScalaArtifacts.LibraryID) :+ compileLibMod + report.withModules(newMods) + }).getOrElse(report) + + val toolReport = updateLibraryToCompileConfiguration( + fullReport + .configuration(Configurations.ScalaTool) + .getOrElse(sys.error(noToolConfiguration(managedScalaInstance.value))) + ) if (Classpaths.isScala213(sv)) { for { @@ -1182,6 +1202,7 @@ object Defaults extends BuildCommon { val allDocJars = fullReport .configuration(Configurations.ScalaDocTool) + .map(updateLibraryToCompileConfiguration) .toSeq .flatMap(_.modules) .flatMap(_.artifacts.map(_._2)) From f0afeff4d99b7946b9094cf453b3a3677dd8575a Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 23 Jan 2024 14:50:06 +0100 Subject: [PATCH 7/9] Set locale for f interpolator decimal character dependency-graph/toFileSubTask failed for me locally --- .../scala/sbt/internal/graph/rendering/Statistics.scala | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/main/src/main/scala/sbt/internal/graph/rendering/Statistics.scala b/main/src/main/scala/sbt/internal/graph/rendering/Statistics.scala index e569b916d..720d15c9f 100644 --- a/main/src/main/scala/sbt/internal/graph/rendering/Statistics.scala +++ b/main/src/main/scala/sbt/internal/graph/rendering/Statistics.scala @@ -47,6 +47,9 @@ object Statistics { } def format(stats: ModuleStats): String = { + import java.util.Locale + val dl = Locale.getDefault + Locale.setDefault(Locale.US) import stats._ def mb(bytes: Long): Double = bytes.toDouble / 1000000 val selfSize = @@ -54,7 +57,10 @@ object Statistics { case Some(size) => f"${mb(size)}%7.3f" case None => "-------" } - f"${mb(transitiveSize)}%7.3f MB $selfSize MB $numTransitiveDependencies%4d $numDirectDependencies%4d ${id.idString}%s" + val r = + f"${mb(transitiveSize)}%7.3f MB $selfSize MB $numTransitiveDependencies%4d $numDirectDependencies%4d ${id.idString}%s" + Locale.setDefault(dl) + r } val allStats = From 4a1ba0c97089d5d301398f6edad238ef59e6d14d Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 23 Jan 2024 17:09:20 +0100 Subject: [PATCH 8/9] tests for standard library unfreezing --- .../stdlib-unfreeze-update/build.sbt | 4 ++ .../stdlib-unfreeze-update/test | 3 ++ .../stdlib-unfreeze/a/A.scala | 20 ++++++++ .../stdlib-unfreeze/a3/A.scala | 17 +++++++ .../stdlib-unfreeze/b/B.scala | 7 +++ .../stdlib-unfreeze/b3/B.scala | 6 +++ .../stdlib-unfreeze/build.sbt | 46 +++++++++++++++++++ .../stdlib-unfreeze/test | 20 ++++++++ 8 files changed, 123 insertions(+) create mode 100644 sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze-update/build.sbt create mode 100644 sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze-update/test create mode 100644 sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/a/A.scala create mode 100644 sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/a3/A.scala create mode 100644 sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/b/B.scala create mode 100644 sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/b3/B.scala create mode 100644 sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/build.sbt create mode 100644 sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/test diff --git a/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze-update/build.sbt b/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze-update/build.sbt new file mode 100644 index 000000000..ed6887bc4 --- /dev/null +++ b/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze-update/build.sbt @@ -0,0 +1,4 @@ +lazy val a = project.settings( + scalaVersion := "2.13.4", + libraryDependencies += "org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.4", // depends on library 2.13.6 +) diff --git a/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze-update/test b/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze-update/test new file mode 100644 index 000000000..7f263ab0b --- /dev/null +++ b/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze-update/test @@ -0,0 +1,3 @@ +-> a/scalaInstance +> set a/scalaVersion := "2.13.6" +> a/scalaInstance diff --git a/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/a/A.scala b/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/a/A.scala new file mode 100644 index 000000000..d1522c579 --- /dev/null +++ b/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/a/A.scala @@ -0,0 +1,20 @@ +import scala.language.reflectiveCalls + +object A extends App { + println(scala.util.Properties.versionString) +} + +object AMacro { + import scala.language.experimental.macros + import scala.reflect.macros.blackbox.Context + + def m(x: Int): Int = macro impl + + def impl(c: Context)(x: c.Expr[Int]): c.Expr[Int] = { + import c.universe._ + // added in 2.13.4 + val ec = (scala.concurrent.ExecutionContext: {def opportunistic: scala.concurrent.ExecutionContextExecutor}).opportunistic + println(ec) + c.Expr(q"2 + $x") + } +} diff --git a/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/a3/A.scala b/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/a3/A.scala new file mode 100644 index 000000000..e6f35a100 --- /dev/null +++ b/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/a3/A.scala @@ -0,0 +1,17 @@ +import scala.quoted.* // imports Quotes, Expr + +package scala.collection { + object Exp: + // added in 2.13.10, not available in 2.13.8 + def m(i: Int) = IterableOnce.checkArraySizeWithinVMLimit(i) +} + +object Mac: + inline def inspect(inline x: Any): Any = ${ inspectCode('x) } + + def inspectCode(x: Expr[Any])(using Quotes): Expr[Any] = + scala.collection.Exp.m(42) + println(x.show) + x + +@main def huhu = println(scala.util.Properties.versionString) diff --git a/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/b/B.scala b/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/b/B.scala new file mode 100644 index 000000000..e24101062 --- /dev/null +++ b/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/b/B.scala @@ -0,0 +1,7 @@ +import java.nio.file.{Paths, Files} +import java.nio.charset.StandardCharsets + +object B extends App { + println(AMacro.m(33)) + Files.write(Paths.get(s"s${scala.util.Properties.versionNumberString}.txt"), "nix".getBytes) +} diff --git a/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/b3/B.scala b/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/b3/B.scala new file mode 100644 index 000000000..a011c5c95 --- /dev/null +++ b/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/b3/B.scala @@ -0,0 +1,6 @@ +import java.nio.file.{Paths, Files} +import java.nio.charset.StandardCharsets + +@main def hubu = + Mac.inspect(println("hai")) + Files.write(Paths.get(s"s${scala.util.Properties.versionNumberString}.txt"), "nix".getBytes) diff --git a/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/build.sbt b/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/build.sbt new file mode 100644 index 000000000..901101cea --- /dev/null +++ b/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/build.sbt @@ -0,0 +1,46 @@ +import sbt.librarymanagement.InclExclRule + +lazy val a = project.settings( + scalaVersion := "2.13.6", + libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, + TaskKey[Unit]("checkLibs") := checkLibs("2.13.6", (Compile/dependencyClasspath).value, ".*scala-(library|reflect).*"), +) + +lazy val b = project.dependsOn(a).settings( + scalaVersion := "2.13.8", + TaskKey[Unit]("checkLibs") := checkLibs("2.13.8", (Compile/dependencyClasspath).value, ".*scala-(library|reflect).*"), +) + +lazy val a3 = project.settings( + scalaVersion := "3.2.2", // 2.13.10 library +) + +lazy val b3 = project.dependsOn(a3).settings( + scalaVersion := "3.2.0", // 2.13.8 library + TaskKey[Unit]("checkScala") := { + val i = scalaInstance.value + i.libraryJars.filter(_.toString.contains("scala-library")).toList match { + case List(l) => assert(l.toString.contains("2.13.10"), i.toString) + } + assert(i.compilerJars.filter(_.toString.contains("scala-library")).isEmpty, i.toString) + assert(i.otherJars.filter(_.toString.contains("scala-library")).isEmpty, i.toString) + }, +) + +lazy val ak = project.settings( + scalaVersion := "2.13.12", + csrSameVersions += Set[InclExclRule]("com.typesafe.akka" % "akka-*"), + libraryDependencies ++= Seq( + "com.typesafe.akka" %% "akka-remote" % "2.6.5", + "com.typesafe.akka" %% "akka-actor" % "2.6.2", + ), + TaskKey[Unit]("checkLibs") := checkLibs("2.6.5", (Compile/dependencyClasspath).value, ".*akka-.*"), +) + +def checkLibs(v: String, cp: Classpath, filter: String): Unit = { + for (p <- cp) + if (p.toString.matches(filter)) { + println(s"$p -- $v") + assert(p.toString.contains(v), p) + } +} diff --git a/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/test b/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/test new file mode 100644 index 000000000..7df93ab6c --- /dev/null +++ b/sbt-app/src/sbt-test/dependency-management/stdlib-unfreeze/test @@ -0,0 +1,20 @@ +> a/checkLibs +> b/checkLibs + +> b/run +$ exists s2.13.8.txt +$ delete s2.13.8.txt + +# don't crash when expanding the macro +> b3/run +$ exists s2.13.10.txt +$ delete s2.13.10.txt + +> b3/checkScala + +# without the default `csrSameVersions`, scala-reflect in b stays at 2.13.6 +> set b/csrSameVersions := Nil +> b/update +-> b/checkLibs + +> ak/checkLibs From 447c2ba5e5f4f6d4259caf7ef188b862fd42a78e Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 26 Feb 2024 13:48:19 +0100 Subject: [PATCH 9/9] update zinc and sbt-coursier dependencies --- project/Dependencies.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index eb5a44714..db9614014 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -15,7 +15,7 @@ object Dependencies { private val ioVersion = nightlyVersion.getOrElse("1.9.7") private val lmVersion = sys.props.get("sbt.build.lm.version").orElse(nightlyVersion).getOrElse("1.9.3") - val zincVersion = nightlyVersion.getOrElse("1.10.0-M2") + val zincVersion = nightlyVersion.getOrElse("1.10.0-M3") private val sbtIO = "org.scala-sbt" %% "io" % ioVersion @@ -77,7 +77,7 @@ object Dependencies { def addSbtZincCompile = addSbtModule(sbtZincPath, "zincCompile", zincCompile) def addSbtZincCompileCore = addSbtModule(sbtZincPath, "zincCompileCore", zincCompileCore) - val lmCoursierShaded = "io.get-coursier" %% "lm-coursier-shaded" % "2.1.3" + val lmCoursierShaded = "io.get-coursier" %% "lm-coursier-shaded" % "2.1.4" def sjsonNew(n: String) = Def.setting("com.eed3si9n" %% n % "0.9.1") // contrabandSjsonNewVersion.value