-
Notifications
You must be signed in to change notification settings - Fork 21
SAM and Subtyping causes AbstractMethodError #10512
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Turns out you don't the implicits at all: trait JV; trait JO extends JV
trait JE {
def enc(a: Any): JV
}
trait JOE extends JE {
def enc(a: Any): JO
}
object Test extends App {
val one: JOE = (a: Any) => null
val two: JE = one
two.enc(12)
} gives
because we're not giving our lambda the right bridges:
I'm sure I've seen this or one of its twins before, though. |
I think you are reffering to 10477 |
If a SAM trait's abstract method overrides a method in a supertrait while changing the return type, the generated invokedynamic instruction needs to pass the types of the overridden methods to `LambdaMetaFactory` so that bridge methods can be added to the generated lambda. Java does this differently: it generates a default method in the subinterface overriding the superinterface method. Theoretically we could also generate the default bridges, but that is a binary-incompatible change, so I think it's safer to just add the bridges in the invokedynamic. Honestly I'm surprised that this hasn't come up already. Fixes scala/bug#10512.
If a SAM trait's abstract method overrides a method in a supertrait while changing the return type, the generated invokedynamic instruction needs to pass the types of the overridden methods to `LambdaMetaFactory` so that bridge methods can be added to the generated lambda. Java does this differently: it generates a default method in the subinterface overriding the superinterface method. Theoretically we could also generate the default bridges, but that is a binary-incompatible change, so I think it's safer to just add the bridges in the invokedynamic. Honestly I'm surprised that this hasn't come up already. Fixes scala/bug#10512.
If a SAM trait's abstract method overrides a method in a supertrait while changing the return type, the generated invokedynamic instruction needs to pass the types of the overridden methods to `LambdaMetaFactory` so that bridge methods can be added to the generated lambda. SAM `Function` trees now have a synthetic `ClassSymbol`, into which we enter an overriding concrete method symbol that represents the runtime LMF-generated implementation of that function. `erasure` then computes bridge methods for that class, which are added to the `LMF.metafactory` call in `jvm`. Java does this instead by generating a default method in the subinterface overriding the superinterface's method. Theoretically, we could generate the bridges in the same way, but that has the downside that the project with the interfaces would need recompiled, which might not be the project that creates the lambdas. Generating bridges the LMF way means that only the classes affected by this bug need to be recompiled to get the fix. Honestly I'm surprised that this hasn't come up already. Fixes scala/bug#10512.
If a SAM trait's abstract method overrides a method in a supertrait while changing the return type, the generated invokedynamic instruction needs to pass the types of the overridden methods to `LambdaMetaFactory` so that bridge methods can be added to the generated lambda. SAM `Function` trees now have a synthetic `ClassSymbol`, into which we enter an overriding concrete method symbol that represents the runtime LMF-generated implementation of that function. `erasure` then computes bridge methods for that class, which are added to the `LMF.metafactory` call in `jvm`. Java does this instead by generating a default method in the subinterface overriding the superinterface's method. Theoretically, we could generate the bridges in the same way, but that has the downside that the project with the interfaces would need recompiled, which might not be the project that creates the lambdas. Generating bridges the LMF way means that only the classes affected by this bug need to be recompiled to get the fix. Honestly I'm surprised that this hasn't come up already. Fixes scala/bug#10512.
If a SAM trait's abstract method overrides a method in a supertrait while changing the return type, the generated invokedynamic instruction needs to pass the types of the overridden methods to `LambdaMetaFactory` so that bridge methods can be added to the generated lambda. SAM `Function` trees now have a synthetic `ClassSymbol`, into which we enter an overriding concrete method symbol that represents the runtime LMF-generated implementation of that function. `erasure` then computes bridge methods for that class, which are added to the `LMF.metafactory` call in `jvm`. Java does this instead by generating a default method in the subinterface overriding the superinterface's method. Theoretically, we could generate the bridges in the same way, but that has the downside that the project with the interfaces would need recompiled, which might not be the project that creates the lambdas. Generating bridges the LMF way means that only the classes affected by this bug need to be recompiled to get the fix. Honestly I'm surprised that this hasn't come up already. Fixes scala/bug#10512.
The following fails on 2.12.3
This seems to be related to SAM, subtyping, implicit resolution and ad-hoc polymorphism.
The bug dissapears under following conditions
listEncoder[A]
(non parameterized types do not cause seem to cause the exception)JsonEncoder[List[A]]
instead of aJsonObjectEncoder[List[A]]
implicit[JsonObjectEncoder[List[String]]]
instead of aimplicit[JsonEncoder[List[String]]]
listEncoder[String].encode(List("a","b"))
This is an edge case that fails at runtime but it seems to me that it should compile and run just fine.
Here is a sample repo that reproduces the bug.
Environnment
Scala: 2.12.3
Java: 1.8.0_102
JVM: HotSpot 25.102-b14
The text was updated successfully, but these errors were encountered: