Move Scala 3 to 3.9.0 LTS - #1623
Merged
Merged
Conversation
Scala 3.9.0 is the new LTS line, superseding 3.3.x. The compiler no longer accepts a Java 11 output target: 3.9.0 sets minReleaseVersion = 17, so `-release:11` is rejected outright with "11 is not a valid choice for -java-output-version". Scala 3 artifacts therefore now require JDK 17 at runtime, and the JVM target moves to 17. For the same reason the temurin@11 CI leg cannot build Scala 3 at all under 3.9 -- its supported release range computes as (17 to 11), i.e. empty -- so the matrix moves to temurin@17 and the workflows are regenerated. The scalacOptions conditional was keyed off a "3.3." version prefix. Left as-is it would have stopped matching and silently dropped the release flag from Scala 3 JVM builds. It is now keyed off the binary version. `-Yfuture-lazy-vals` is dropped with it: the setting no longer exists in 3.9.0, so passing it would fail the build. Scala 2.13 keeps -release:8. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QRbVCYWp3bquNaXPYW12JY
The JS and Native settings added -release:8 unconditionally, which only worked because Scala 3 was pinned to 3.3.8. Scala 3 has rejected targets below 17 since 3.8 (minReleaseVersion = 17), so under 3.9.0 both fail with "8 is not a valid choice for -java-output-version". Route all three platforms through a single releaseOption keyed off the binary version, so Scala 3 gets -release:17 and Scala 2.13 keeps -release:8 everywhere. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QRbVCYWp3bquNaXPYW12JY
scalaNextTest depends on core, which is now built by 3.9.0 and emits TASTy 28.9. The 3.8.4 compiler reads at most 28.8, so the Scala Next jobs failed with "Forward incompatible TASTy file has version 28.9 [...] expected stable TASTy from 28.0 to 28.8". The project exists to exercise the compiler line ahead of the one we publish, so it has to move past 3.9.0 rather than trail it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QRbVCYWp3bquNaXPYW12JY
scalaNextTest existed for one reason: NamedTuple support could not be tested on the version we published against, because scala/NamedTuple does not exist in 3.3.x at all. It held two files and needed a separate compiler, a version skew, and a scalacOptions workaround to carry them. On 3.9.0 NamedTuple is present and no longer experimental, so the two tests compile and run in the ordinary test project on the same compiler as everything else. That removes the project, scalaNextVersion (and with it the 3.10.0-RC1 prerelease from CI), the "-release:8"/"-Ykind-projector" removal that only papered over the version mismatch, and three CI steps. The tests move to test/shared/src/test/scala-3, so they stay Scala 3 only and 2.13 does not see them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QRbVCYWp3bquNaXPYW12JY
julien-truffaut
force-pushed
the
scala-3.9-lts
branch
from
September 4, 2026 14:11
8464bc6 to
65ec6a4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Moves the Scala 3 build from 3.3.8 to 3.9.0 LTS (released 2026-09-03).
Warning
This raises the JDK baseline for Scala 3 artifacts from 11 to 17. That is forced by the compiler, not a preference — see below.
Why the JDK baseline has to move
3.9.0 will not emit Java 11 bytecode. From
ScalaSettingsProperties.scalaat tag 3.9.0:Against 3.3.8, where the minimum came from the full
classfileVersionMapand went down to Java 8. Keeping-release:11fails the build outright:The same limit rules out the
temurin@11CI leg: supported release versions are computed as(minReleaseVersion to min(jdkVersion, maxTargetVersion)), which on JDK 11 is(17 to 11)— an empty range. So the matrix moves totemurin@17and the workflows are regenerated.Scala 2.13 is unaffected and keeps
-release:8.The release flag now follows the binary version, on every platform
monocleJvmSettingskeyed its flags off a string prefix, and the JS and Native settings added-release:8unconditionally:Two separate problems there. On the JVM, bumping the version alone would have stopped matching the first branch and silently dropped the release flag — no error, just a changed bytecode target in published artifacts. On JS and Native,
-release:8is rejected outright under 3.9 (8 is not a valid choice for -java-output-version); it only ever worked because Scala 3 was pinned at 3.3.8.All three now route through one setting:
-Yfuture-lazy-valsgoes too: the setting exists in 3.3.8 but was removed in 3.9.0, so passing it would fail the build. Its behaviour is the default now.scalaNextVersion 3.8.4 → 3.10.0-RC1
scalaNextTestdepends oncore, now built by 3.9.0 and emitting TASTy 28.9. The 3.8.4 compiler reads at most 28.8:The project exists to exercise the line ahead of what we publish, so it has to move past 3.9.0 rather than trail it. Note this puts an RC in CI — deliberate, and the reason
scalaNextTestexists, but worth flagging.Verification
Run locally on 3.9.0:
rootJVM/test— 2006 tests, 0 failurescoreJVM/coreJS/coreNative/macrosJS/macrosNativecompilescalaNextTestJVM/teston 3.10.0-RC1 against 3.9.0-builtcore— 36 tests, 0 failuresmimaReportBinaryIssues,scalafmtSbtCheck,githubWorkflowCheckall clean-release:17on Scala 3 and-release:8on 2.13As a side effect the regenerated workflow clears the
Using JDK 11 with Scala Native ... is deprecatedandUsing sbt-scalajs on JDK 11 is deprecatedwarnings that were showing up in release logs — both wanted JDK 17 already.🤖 Generated with Claude Code
https://claude.ai/code/session_01QRbVCYWp3bquNaXPYW12JY