pjfanning opened a new issue, #3750:
URL: https://github.com/apache/pekko/issues/3750
### Summary
The wildcard bounds added to the typed Java DSL in #3720 stop Scala 2.13
callers from passing a function literal to overloaded methods such as
`CommandHandlerBuilderByState.onCommand` and
`EventHandlerBuilderByState.onEvent`. Code that compiled against 2.0.0-M4 fails
against 2.0.0.
Java callers and Scala 3 callers are not affected. This came up in
`grpc-int-test` while updating pekko-projection to 2.0.0
(apache/pekko-projection#674). Calling the Java DSL from Scala is unusual, so
this may only need documenting, but it is a source incompatibility for anyone
who does it.
### Reproducer with Pekko
```scala
import org.apache.pekko.persistence.typed.PersistenceId
import org.apache.pekko.persistence.typed.javadsl._
object Repro {
sealed trait Command
final case class Get() extends Command
final case class Changed()
final case class State()
class Behavior(id: PersistenceId) extends EventSourcedBehavior[Command,
Changed, State](id) {
override def emptyState: State = State()
override def commandHandler(): CommandHandler[Command, Changed, State] =
newCommandHandlerBuilder()
.forAnyState()
.onCommand(classOf[Get], { (state: State, command: Get) =>
Effect.none() })
.build()
override def eventHandler(): EventHandler[State, Changed] =
newEventHandlerBuilder()
.forAnyState()
.onEvent(classOf[Changed], { (state: State, event: Changed) => state
})
.build()
}
}
```
```shell
scala-cli compile -S 2.13.18 --dep
"org.apache.pekko::pekko-persistence-typed:2.0.0" Repro.scala
```
```
error: overloaded method onCommand with alternatives:
[C <: Repro.Command](commandClass: Class[C], handler:
java.util.function.BiFunction[_ >: Repro.State, _ >: C, _ <:
...Effect[Repro.Changed,Repro.State]]): ... <and>
(predicate: java.util.function.Predicate[_ >: Repro.Command],handler:
java.util.function.BiFunction[_ >: Repro.State, _ >: Repro.Command, _ <:
...Effect[Repro.Changed,Repro.State]])...
cannot be applied to (Class[Repro.Get], (Repro.State, Repro.Get) =>
...EffectBuilder[Repro.Changed,Repro.State])
```
### Reduced reproducer without Pekko
```scala
import java.util.function.{ BiFunction, Predicate }
object Repro {
trait Cmd; class Get extends Cmd; class St; class Eff; class EffB extends
Eff
class Builder[S] {
def on[C <: Cmd](c: Class[C], f: BiFunction[_ >: S, _ >: C, _ <: Eff]):
Unit = ()
def on(p: Predicate[_ >: Cmd], f: BiFunction[_ >: S, _ >: Cmd, _ <:
Eff]): Unit = ()
}
new Builder[St].on(classOf[Get], { (s: St, g: Get) => new EffB })
}
```
| Variant of the reduced reproducer | Scala 2.13.18 | Scala 3.3.9 |
|---|---|---|
| Overloaded, wildcard bounds (above) | fails | compiles |
| Overloaded, no wildcards (`BiFunction[S, C, Eff]`, `Predicate[Cmd]`) |
compiles | compiles |
| Only the `Class[C]` method, wildcard bounds, no overload | compiles |
compiles |
So the failure needs both overloading and wildcard bounds. Neither one fails
alone.
### Results
| Caller | 2.0.0-M4 | 2.0.0 |
|---|---|---|
| Scala 2.13.18, function literal | compiles | **fails** |
| Scala 3.3.9, function literal | not tested | compiles |
| Java 17, lambda (inferred or explicit parameter types) | compiles |
compiles |
| Java 17, pre-typed `BiFunction<Object, Command, Effect<Changed, State>>` |
fails | compiles |
The last row is the case #3720 set out to enable, so the widening does what
it intended for Java.
### Workaround for Scala 2.13
Ascribe each function literal to a concrete `BiFunction` type. This compiles
on Scala 2.13.18 and 3.3.9:
```scala
import java.util.function.BiFunction
newCommandHandlerBuilder()
.forAnyState()
.onCommand(classOf[Get],
{ (state: State, command: Get) => Effect.none() }: BiFunction[State,
Get, Effect[Changed, State]])
.build()
newEventHandlerBuilder()
.forAnyState()
.onEvent(classOf[Changed], { (state: State, event: Changed) => state }:
BiFunction[State, Changed, State])
.build()
```
An explicit type argument is not enough. `.onCommand[Get](classOf[Get],
...)` and `.onEvent[Changed](classOf[Changed], ...)` still fail against 2.0.0,
because `BiFunction`, `Function` and `Supplier` overloads all take a `Class[C]`.
### Scope and open question
Only the `BiFunction` overloads of `onCommand` and `onEvent` were tested.
#3720 widened other typed Java DSL methods, and overloaded ones may behave the
same way from Scala 2.13.
Should this be documented as a known limitation, for example in the
migration notes, or is there a way to keep these overloads usable from Scala
2.13 without giving up the widening for Java?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]