mirror of https://github.com/sbt/sbt.git
Merge pull request #8912 from bitloi/fix/6694-scala3-eviction-downgrade
[2.x] feat: Eviction error for downgrade of Scala 3.x
This commit is contained in:
commit
a1f6fd2f65
|
|
@ -826,6 +826,7 @@ lazy val serverTestProj = (project in file("server-test"))
|
|||
.dependsOn(sbtProj % "compile->test", scriptedSbtProj % "compile->test")
|
||||
.settings(
|
||||
testedBaseSettings,
|
||||
allowUnsafeScalaLibUpgrade := true, // demote Scala 3 eviction to warn if deps bring newer scala3-library_3
|
||||
Utils.noPublish,
|
||||
// make server tests serial
|
||||
Test / watchTriggers += baseDirectory.value.toGlob / "src" / "server-test" / **,
|
||||
|
|
|
|||
|
|
@ -158,6 +158,34 @@ object Compiler:
|
|||
val fullReport = Keys.update.value
|
||||
val s = Keys.streams.value
|
||||
|
||||
def reportScalaLibEviction(
|
||||
proj: String,
|
||||
sv: String,
|
||||
libVer: String,
|
||||
libName: String,
|
||||
err: Boolean,
|
||||
alignmentLine: String,
|
||||
evictedLine: String
|
||||
): Unit =
|
||||
val fix =
|
||||
if err then
|
||||
"""Upgrade the `scalaVersion` to fix the build. If upgrading the Scala compiler version is
|
||||
|not possible (for example due to a regression in the compiler or a missing dependency),
|
||||
|this error can be demoted by setting `allowUnsafeScalaLibUpgrade := true`.""".stripMargin
|
||||
else s"""Note that the dependency classpath and the runtime classpath of your project
|
||||
|contain the newer $libName $libVer, even if the scalaVersion is $sv.
|
||||
|Compilation (macro expansion) or using the Scala REPL in sbt may fail with a LinkageError.""".stripMargin
|
||||
val msg =
|
||||
s"""Expected `$proj scalaVersion` to be $libVer or later, but found $sv.
|
||||
|$alignmentLine
|
||||
|
|
||||
|$fix
|
||||
|
|
||||
|$evictedLine
|
||||
|""".stripMargin
|
||||
if err then sys.error(msg)
|
||||
else s.log.warn(msg)
|
||||
|
||||
// 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.
|
||||
|
|
@ -194,26 +222,39 @@ object Compiler:
|
|||
val proj =
|
||||
Def.displayBuildRelative(Keys.thisProjectRef.value.build, Keys.thisProjectRef.value)
|
||||
if VersionNumber(sv).matchesSemVer(SemanticSelector(s"<$libVer")) then
|
||||
val err = !Keys.allowUnsafeScalaLibUpgrade.value
|
||||
val fix =
|
||||
if err then
|
||||
"""Upgrade the `scalaVersion` to fix the build. If upgrading the Scala compiler version is
|
||||
|not possible (for example due to a regression in the compiler or a missing dependency),
|
||||
|this error can be demoted by setting `allowUnsafeScalaLibUpgrade := true`.""".stripMargin
|
||||
else s"""Note that the dependency classpath and the runtime classpath of your project
|
||||
|contain the newer $libName $libVer, even if the scalaVersion is $sv.
|
||||
|Compilation (macro expansion) or using the Scala REPL in sbt may fail with a LinkageError.""".stripMargin
|
||||
val msg =
|
||||
s"""Expected `$proj scalaVersion` to be $libVer or later, but found $sv.
|
||||
|To support backwards-only binary compatibility (SIP-51), the Scala 2.13 compiler
|
||||
|should not be older than $libName on the dependency classpath.
|
||||
|
|
||||
|$fix
|
||||
|
|
||||
|See `$proj evicted` to know why $libName $libVer is getting pulled in.
|
||||
|""".stripMargin
|
||||
if err then sys.error(msg)
|
||||
else s.log.warn(msg)
|
||||
reportScalaLibEviction(
|
||||
proj,
|
||||
sv,
|
||||
libVer,
|
||||
libName,
|
||||
!Keys.allowUnsafeScalaLibUpgrade.value,
|
||||
s"""To support backwards-only binary compatibility (SIP-51), the Scala 2.13 compiler
|
||||
|should not be older than $libName on the dependency classpath.""".stripMargin,
|
||||
s"See `$proj evicted` to know why $libName $libVer is getting pulled in."
|
||||
)
|
||||
else ()
|
||||
else if ScalaArtifacts.isScala3(sv) then
|
||||
val scala3LibOpt = for
|
||||
compileReport <- fullReport.configuration(Configurations.Compile)
|
||||
lib <- compileReport.modules.find(
|
||||
_.module.name.startsWith(ScalaArtifacts.Scala3LibraryPrefix)
|
||||
)
|
||||
yield lib
|
||||
for lib <- scala3LibOpt do
|
||||
val libVer = lib.module.revision
|
||||
val libName = lib.module.name
|
||||
val proj =
|
||||
Def.displayBuildRelative(Keys.thisProjectRef.value.build, Keys.thisProjectRef.value)
|
||||
if VersionNumber(sv).matchesSemVer(SemanticSelector(s"<$libVer")) then
|
||||
reportScalaLibEviction(
|
||||
proj,
|
||||
sv,
|
||||
libVer,
|
||||
libName,
|
||||
!Keys.allowUnsafeScalaLibUpgrade.value,
|
||||
s"To maintain the compile-time alignment, the Scala compiler cannot be older than $libName on the dependency classpath.",
|
||||
s"See `$proj evicted` to know why $libName was upgraded from $sv to $libVer."
|
||||
)
|
||||
else ()
|
||||
else ()
|
||||
def file(id: String): Option[File] =
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
// Regression test for #6694: Scala 3 eviction error when scalaVersion < scala3-library_3 on classpath.
|
||||
// low has scalaVersion 3.3.2 and depends on high (3.3.4), so resolved scala3-library_3 is 3.3.4.
|
||||
// Without allowUnsafeScalaLibUpgrade, compile must fail with the eviction error.
|
||||
|
||||
lazy val high = project.settings(
|
||||
scalaVersion := "3.3.4",
|
||||
)
|
||||
|
||||
lazy val low = project.dependsOn(high).settings(
|
||||
scalaVersion := "3.3.2",
|
||||
// do NOT set allowUnsafeScalaLibUpgrade — we expect the build to fail
|
||||
)
|
||||
|
|
@ -0,0 +1 @@
|
|||
object H { def id[A](a: A): A = a }
|
||||
|
|
@ -0,0 +1 @@
|
|||
object L { def main(args: Array[String]): Unit = println(H.id(1)) }
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
# Expect compile to fail: scalaVersion 3.3.2 < scala3-library_3 3.3.4 from high
|
||||
-> low/compile
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
// Same as stdlib-unfreeze-scala3-eviction but with allowUnsafeScalaLibUpgrade := true on low.
|
||||
// low has scalaVersion 3.3.2 and depends on high (3.3.4); we demote the eviction to a warning so compile succeeds.
|
||||
|
||||
lazy val high = project.settings(
|
||||
scalaVersion := "3.3.4",
|
||||
)
|
||||
|
||||
lazy val low = project.dependsOn(high).settings(
|
||||
allowUnsafeScalaLibUpgrade := true,
|
||||
scalaVersion := "3.3.2",
|
||||
)
|
||||
|
|
@ -0,0 +1 @@
|
|||
object H { def id[A](a: A): A = a }
|
||||
|
|
@ -0,0 +1 @@
|
|||
object L { def main(args: Array[String]): Unit = println(H.id(1)) }
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# With allowUnsafeScalaLibUpgrade := true, compile and run succeed (eviction is a warning only)
|
||||
> low/compile
|
||||
> low/run
|
||||
|
|
@ -16,6 +16,7 @@ lazy val a3 = project.settings(
|
|||
)
|
||||
|
||||
lazy val b3 = project.dependsOn(a3).settings(
|
||||
allowUnsafeScalaLibUpgrade := true, // b3 has 3.3.2, a3 brings 3.3.4; demote to warn so b3/run still passes
|
||||
scalaVersion := "3.3.2", // 2.13.12 library
|
||||
TaskKey[Unit]("checkScala") := {
|
||||
val i = scalaInstance.value
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
ThisBuild / scalaVersion := "3-latest.candidate"
|
||||
ThisBuild / allowUnsafeScalaLibUpgrade := true // dynamic scalaVersion (3-latest.candidate) vs resolved scala3-library_3; demote to warn
|
||||
|
||||
lazy val checkDynVersion = taskKey[Unit]("Check that scalaDynVersion resolves correctly")
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue