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]

Reply via email to