[JVM_IR] Fix interface method resolution
The JVM IR was too agressive in delegating statically to $DefaultImpls
class.
Consider the following library, compiled separately, and then client,
compiled against that library:
```
//library
interface A { @JvmDefault fun foo() = "A" }
interface Left : A { }
interface Right : A { @JvmDefault override fun foo() = "Right" }
//client
interface C : Left, Right {}
fun main() {
val x = object : C {}
println(x.foo())
}
```
Previously, the IR backend generates an overriding bridge in C, which
calls C$DefaultImpls which calls statically into Right$DefaultImpls.
When then library is recompilerd with an override of foo in Left, the
existing binary of the client continues to run against the recompiled
library erroneously running Right.foo().
The old backend throws an IncompatibleClassChange exception due to
ambiguity of multiple inherited default implementations. kotlinc indeed
rejects the client when recompiled against the new library.
We have no tests constraining this behaviour, but we could conceivably
strap something together in CustomBinaries tests.
This commit is contained in:
committed by
max-kammerer
parent
df96841c9d
commit
6a41700689
+1
-1
@@ -79,7 +79,7 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl
|
||||
|| Visibilities.isPrivate(implementation.visibility)
|
||||
|| implementation.isDefinitelyNotDefaultImplsMethod()
|
||||
|| implementation.isMethodOfAny()
|
||||
|| (!context.state.jvmDefaultMode.isCompatibility && implementation.hasJvmDefault())
|
||||
|| implementation.hasJvmDefault()
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user