mirror of https://github.com/sbt/sbt.git
[2.x] fix: Eviction error for downgrade of Scala 3.x (#6694)
**Problem** When scalaVersion is Scala 3.x and a dependency brings a newer scala3-library_3, sbt did not report an eviction error or warning. The compiler could be older than the standard library on the classpath, breaking compile-time alignment (e.g. scala/scala3#25406). **Solution** - In Compiler.scala, add an else if ScalaArtifacts.isScala3(sv) branch in scalaInstanceConfigFromUpdate that finds scala3-library_* on the Compile report and, if scalaVersion < that revision, fails (or warns when allowUnsafeScalaLibUpgrade := true) with the same pattern as the existing Scala 2.13 check (PR 7480). Message uses compile-time alignment wording and "See evicted to know why ... was upgraded from". - Set allowUnsafeScalaLibUpgrade := true on b3 in stdlib-unfreeze so existing b3/run and b3/checkScala still pass. - Add scripted tests: stdlib-unfreeze-scala3-eviction (expect compile to fail) and stdlib-unfreeze-scala3-warn (expect success with warning). Closes #6694
This commit is contained in:
parent
ed501b71bd
commit
f4eff2da77
|
|
@ -215,6 +215,39 @@ object Compiler:
|
|||
if err then sys.error(msg)
|
||||
else s.log.warn(msg)
|
||||
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
|
||||
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 maintain the compile-time alignment, the Scala compiler cannot be older than $libName on the dependency classpath.
|
||||
|
|
||||
|$fix
|
||||
|
|
||||
|See `$proj evicted` to know why $libName was upgraded from $sv to $libVer.
|
||||
|""".stripMargin
|
||||
if err then sys.error(msg)
|
||||
else s.log.warn(msg)
|
||||
else ()
|
||||
else ()
|
||||
def file(id: String): Option[File] =
|
||||
for
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue