Compiler version
- 3.9.0-RC2
- 3.9.0-RC3
- 3.10.0-RC1-bin-20260712-f51c618-NIGHTLY
The same code works with 3.8.3 and 3.9.0-RC1, so the regression starts in 3.9.0-RC2.
Minimized code
Repro.scala:
package repro
import java.util.function.Consumer
final class Builder[T] {
def accept[M <: T](clazz: Class[M], consumer: Consumer[M]): Unit = ()
}
Use.java:
package repro;
final class Use {
interface Command {}
static final class Create implements Command {}
void test(Builder<Command> builder) {
builder.accept(Create.class, (Create command) -> {});
}
}
Compile with:
scala-cli compile Repro.scala -S 3.9.0-RC3 --server=false -d out
javac -cp out -d out Use.java
Output
Use.java:8: error: incompatible types: Class<Create> cannot be converted to Class<Command>
builder.accept(Create.class, (Create command) -> {});
^
javap -p -s repro.Builder shows that the method type parameter M is declared, but all of its uses are replaced with the outer type parameter T:
public <M extends T> void accept(java.lang.Class<T>, java.util.function.Consumer<T>);
With 3.8.3 and 3.9.0-RC1, the generated signature is:
public <M extends T> void accept(java.lang.Class<M>, java.util.function.Consumer<M>);
Expectation
The method type variable M has upper bound T, but it remains a distinct type variable. Its occurrences in Class[M] and Consumer[M] must therefore be encoded as M, as they were before 3.9.0-RC2. Java should be able to infer M = Create and compile the call.
This breaks Java-facing generic APIs in Apache Pekko PR #3303, including BehaviorBuilder[T].onMessage[M <: T], where valid Java method references no longer compile. The affected compiler area overlaps the generic-signature rewrite in #25880.
Compiler version
The same code works with 3.8.3 and 3.9.0-RC1, so the regression starts in 3.9.0-RC2.
Minimized code
Repro.scala:Use.java:Compile with:
Output
javap -p -s repro.Buildershows that the method type parameterMis declared, but all of its uses are replaced with the outer type parameterT:With 3.8.3 and 3.9.0-RC1, the generated signature is:
Expectation
The method type variable
Mhas upper boundT, but it remains a distinct type variable. Its occurrences inClass[M]andConsumer[M]must therefore be encoded asM, as they were before 3.9.0-RC2. Java should be able to inferM = Createand compile the call.This breaks Java-facing generic APIs in Apache Pekko PR #3303, including
BehaviorBuilder[T].onMessage[M <: T], where valid Java method references no longer compile. The affected compiler area overlaps the generic-signature rewrite in #25880.