This is an automated email from the ASF dual-hosted git repository.
He-Pin pushed a commit to branch optimize-stage-actor-ref-lazy-dispatch
in repository https://gitbox.apache.org/repos/asf/pekko.git
The following commit(s) were added to
refs/heads/optimize-stage-actor-ref-lazy-dispatch by this push:
new f53c08024d fix: cross-compile LazyDispatch on Scala 3 (VarHandle +
access)
f53c08024d is described below
commit f53c08024d45ff765ebb40c7478f0a4cc8fef99b
Author: He-Pin <[email protected]>
AuthorDate: Wed Jun 3 13:14:07 2026 +0800
fix: cross-compile LazyDispatch on Scala 3 (VarHandle + access)
Motivation:
The squashed PR #3035 fails Binary Compatibility and Tests (3.3.x) on Scala
3 for
two reasons: (1) `schedStateHandle.getAcquire(this).asInstanceOf[Int]`
cannot be
resolved — Scala 3's strict inference cannot pick the Int-returning
signature-
polymorphic overload from a chained `.asInstanceOf` call site, defaulting
the
return to Object and rejecting the primitive comparison; (2) `private final
class
LazyDispatch` is unreachable from `class StageActor`'s aux constructor on
Scala 3,
which compiles the aux ctor outside the companion object.
Modification:
Read state through a typed local (`val cur: Int =
schedStateHandle.getAcquire(this)`)
so the call site witnesses the Int-returning overload of the
polymorphic-signature
method. Drop `private` from `class LazyDispatch` (the enclosing `object
StageActor`
is itself private, so the class stays internally scoped). Preserves the
VarHandle —
no per-instance AtomicInteger, no extra wrapper allocation.
Result:
Scala 2.13 + Scala 3.3 compile clean, stream / mimaReportBinaryIssues
passes,
scalafmt clean, StageActorRefSpec 11/11 green.
---
.../main/scala/org/apache/pekko/stream/stage/GraphStage.scala | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git
a/stream/src/main/scala/org/apache/pekko/stream/stage/GraphStage.scala
b/stream/src/main/scala/org/apache/pekko/stream/stage/GraphStage.scala
index b676e1c29d..4285dc6024 100644
--- a/stream/src/main/scala/org/apache/pekko/stream/stage/GraphStage.scala
+++ b/stream/src/main/scala/org/apache/pekko/stream/stage/GraphStage.scala
@@ -365,7 +365,9 @@ object GraphStageLogic {
* is forced by the public `StageActorRef.Receive` type. No AsyncInput
/ Envelope per tell — those are
* amortized across the batch.
*/
- private final class LazyDispatch(
+ // Not marked `private` so that `class StageActor`'s aux constructor
(compiled outside of the companion
+ // object on Scala 3) can reference it; the enclosing `object StageActor`
is itself private.
+ final class LazyDispatch(
interpreter: GraphInterpreter,
logic: GraphStageLogic,
handler: Any => Unit,
@@ -386,7 +388,10 @@ object GraphStageLogic {
add(pair) // Vyukov producer path: getAndSet + release-store, no CAS
spin
// Double-checked CAS: uncontended fast path is one acquire-load; only
the IDLE->SCHEDULED winner
// pays a CAS + mailbox push.
- if (schedStateHandle.getAcquire(this).asInstanceOf[Int] ==
SchedStateIdle &&
+ // The typed local witnesses the Int-returning signature-polymorphic
overload of getAcquire —
+ // Scala 3's strict inference otherwise defaults the return to Object
and rejects the comparison.
+ val cur: Int = schedStateHandle.getAcquire(this)
+ if (cur == SchedStateIdle &&
schedStateHandle.compareAndSet(this, SchedStateIdle,
SchedStateScheduled))
scheduleDrain()
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]