Fix Scala 3.8.4 compilation compatibility while preserving 2.13 and 3.3.x cross-build#3060
Fix Scala 3.8.4 compilation compatibility while preserving 2.13 and 3.3.x cross-build#3060He-Pin wants to merge 2 commits into
Conversation
812a6d1 to
913415e
Compare
… cross-build Motivation: The codebase needs to compile with both Scala 3.3.x (current production) and Scala 3.8.4 (forward compatibility for upcoming 3.9 LTS). Several patterns valid in 3.3.x are errors or warnings in 3.8.4. Modification: - Merge PersistencePlugin [T: ClassTag] context bound and (implicit ev: PluginProvider) into a single implicit parameter list so subclasses can pass both arguments without the `using` keyword (cross-compatible with Scala 2.13 and 3.3.x) - Replace explicit ClassTag passing `method(arg)(ClassTag(clazz))` with `implicit val ct = ClassTag(clazz); method(arg)` pattern throughout the codebase (context bounds become `using` clauses in Scala 3.8, making positional passing an error) - Fix SortedSet.empty(ordering) / TreeSet.empty(ordering) across cluster, cluster-tools, cluster-sharding, distributed-data modules by binding the Ordering as an implicit val before calling .empty[Member] - Add @unchecked to type-test patterns that cannot be checked at runtime (Reachability.scala, AskPattern.scala) - Fix `_` wildcard type argument to `?` in scala-3-only source files - Fix LogSource resolution in MultiNodeSpec (classOf instead of this.getClass) - Fix "pure expression does nothing" in FixedBufferSpec structural type calls - Remove discarded non-Unit value (unused Success) in SnapshotStorage - Add -Wconf suppression rules for Scala 3.8 deprecation and syntax warnings in PekkoDisciplinePlugin (both main and test scopes) Result: All modules compile successfully with both Scala 2.13.18 and Scala 3.8.4. Cross-compilation with Scala 2.13 is preserved. No `using` keyword is used in shared source files. Tests: - sbt "++3.8.4" "Test / compile" — success - sbt "Test / compile" (2.13) — success (docs module has pre-existing unused warnings) References: None - proactive Scala 3.8 forward compatibility
913415e to
462dff8
Compare
…ations Motivation: The initial Scala 3.8 compatibility changes had some code duplication, unnecessary type casts, and could be simplified in several places. Modification: - Extract shared isScala3_8Plus method in JdkOptions to eliminate duplication with Jdk9.scala - Re-add Scala 3.8 -Wconf suppressions in PekkoDisciplinePlugin with deduplication using shared scala3Suppressions/scala3DocSuppressions - Simplify BehaviorTestKitSpec messageAdapter by removing unnecessary asInstanceOf and using proper ClassTag[U] type parameter - Simplify ActorContextSpec ClassTag.Null passing by using explicit parameter instead of implicit val with @nowarn Result: Cleaner, more maintainable Scala 3.8 compatibility code with less duplication and unnecessary type casts. Tests: Not run - code simplifications only, no behavior changes References: Refs #3060
…estKit Motivation: PR #3060 CI was failing with two categories of errors on Scala 2.13: 1. ~100 fatal warnings in docs/Test/compile from unused imports, locals, and pattern variables that were not suppressed 2. "not found: type U" in BehaviorTestKitSpec due to type erasure in pattern matching Modification: - PekkoDisciplinePlugin: add docsScala2Suppressions with explicit -Wconf rules for each unused subcategory (unused-imports, unused-locals, unused-pat-vars, etc.) because Scala 2.13's -Wconf uses exact string matching, so cat=unused:s does not match subcategories - BehaviorTestKitSpec: revert ClassTag[U] change back to explicit ClassTag(messageClass) passing since U is not in scope during pattern matching of CreateMessageAdapter Result: docs/Test/compile and actor-testkit-typed/Test/compile pass on both Scala 2.13.18 and 3.3.8 Tests: - sbt "++ 2.13.18 docs/Test/compile" — success (30 compilation units) - sbt "++ 3.3.8 docs/Test/compile" — success - sbt "++ 2.13.18 actor-testkit-typed/Test/compile" — success - sbt "++ 3.3.8 actor-testkit-typed/Test/compile" — success References: Fixes CI failures on PR #3060
…docs Test compilation Motivation: The docs module Test compilation fails on Scala 2.13 CI with unused-imports, unused-params, unused-pat-vars, and unused-locals warnings treated as errors. The PR split -Wconf rules from a single comma-separated string into separate -Wconf:xxx scalacOptions entries. When split, the -Wconf:any:e catch-all overrides the category-specific suppressions due to Scala 2.13's -Wconf first-match-wins semantics across separate compiler options. Modification: Merge the split -Wconf options back into single comma-separated strings in defaultScalaOptions, docs Compile overrides, and docs Test overrides. This restores the original -Wconf rule evaluation order where category-specific suppressions (cat=unused:s, cat=deprecation:s, cat=unchecked:s) take effect before the any:e catch-all within the same compiler option. Result: docs/Test compiles successfully with both Scala 2.13.18 and Scala 3.3.8. All core modules (actor, actor-typed, persistence, cluster) compile with Scala 2.13. The Scala 3.8 forward compatibility changes remain intact. Tests: - sbt "docs / Test / compile" (Scala 2.13.18) — success - sbt "++3.3.8" "docs / Test / compile" — success - sbt "actor/Test/compile" "actor-typed/Test/compile" "persistence/Test/compile" "cluster/Test/compile" (2.13) — success References: Refs apache#3060
| case CreateMessageAdapter(messageClass, f, replyTo) => | ||
| val adaptor = context.messageAdapter(f)(ClassTag(messageClass)) | ||
| implicit val ct: ClassTag[Any] = ClassTag(messageClass) | ||
| val adaptor = context.messageAdapter[Any](f.asInstanceOf[Any => Command]) |
There was a problem hiding this comment.
it's ok to make this change but the casting seems weird and could be a bug in scala 3.8
There was a problem hiding this comment.
Agreed, the asInstanceOf cast was a workaround for Scala 3.8 context bound desugaring. It has been reverted to the original context.messageAdapter(f)(ClassTag(messageClass)) pattern in commit 683f874 — the explicit ClassTag passing still works correctly in Scala 3.8 since using parameters can be passed positionally. The refactored ClassTag[U] version did not compile on Scala 2.13 because U is erased in pattern matching.
|
The 3.9.0-RC1 has just been released, hope this will make the code compiles with 3.9.0-RC1 |
|
Closing to reopen with a rebased branch that resolves merge conflicts with main (Hub.scala private[this] changes from #3063). |
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
usingclauses), stricter deprecation warnings, and syntax changes.Modification
171 files changed across the codebase:
ClassTag context bound fixes: In Scala 3.8,
[T: ClassTag]desugars to ausingclause, making explicitClassTagpassing positional-incompatible. Fixed by usingimplicit 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 singleimplicitparameter list(implicit ct: ClassTag[T], ev: PluginProvider[T, ScalaDsl, JavaDsl])to avoid context bound + separate implicit parameter mismatch in Scala 3.8..apply()trick: Useddecoration[T].apply(behavior)instead ofdecoration[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 deprecatesprivate[this]in favor ofprivate.= _initializers → explicit defaults: Replaced= _with= null,= None,= 0, etc. as Scala 3.8 deprecates uninitialized vars.SortedSet.empty(ordering)fix: Bound ordering asimplicit val ordbefore calling.empty[Member]to avoid implicit resolution issues.@uncheckedannotations: Added for type-test patterns that can't be checked at runtime under Scala 3.@nowarnfilters: Used message-based@nowarn("msg=never used")instead of category-based filters for cross-version compatibility.PekkoDisciplinePlugin.scala: Added-Wconfsuppression rules for Scala 3.8 deprecation/syntax warnings in both main and test scopes.No
usingkeyword in shared sources: All changes use cross-compatible patterns (implicit val,.apply()trick). Theusingkeyword only appears inscala-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 modulessbt "Test / compile"(Scala 2.13.18) — success across all modulesReferences
None - proactive Scala 3.8 forward compatibility