JVM IR: fix InterfaceLowering for $default methods from base interfaces
The first change here is swapping the isCompatibility and hasJvmDefault checks. Otherwise behavior could be different depending on -Xjvm-default mode even for non-JvmDefault declarations, which makes little sense. Another change is avoiding generating $default stubs for fake overrides in interfaces, which replicates the behavior of the current backend. (Note that this change also fixes the first problem on the newly added tests, but the first change seems useful anyway.)
This commit is contained in:
+13
-10
@@ -71,12 +71,13 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
|
||||
continue@loop
|
||||
|
||||
/**
|
||||
* 2) They inherit a default implementation from an interface this interface
|
||||
* extends: create a bridge from companion to companion, unless
|
||||
* - the implementation is private or belongs to java.lang.Object
|
||||
* - we're in JVM Compatibility Default mode, in which case we go via
|
||||
* 2) They inherit a default implementation from an interface this interface extends:
|
||||
* create a bridge from DefaultImpls of derived to DefaultImpls of base, unless
|
||||
* - the implementation is private, or belongs to java.lang.Object,
|
||||
* or is a stub for function with default parameters ($default)
|
||||
* - we're in -Xjvm-default=compatibility mode, in which case we go via
|
||||
* accessors on the parent class rather than the DefaultImpls
|
||||
* - we're in JVM Default mode, and we have that default implementation,
|
||||
* - we're in -Xjvm-default=enable mode, and we have that default implementation,
|
||||
* in which case we simply leave it.
|
||||
*
|
||||
* ```
|
||||
@@ -95,18 +96,20 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
|
||||
val implementation = function.resolveFakeOverride()!!
|
||||
|
||||
when {
|
||||
Visibilities.isPrivate(implementation.visibility) || implementation.isMethodOfAny() ->
|
||||
Visibilities.isPrivate(implementation.visibility) ||
|
||||
implementation.isMethodOfAny() ||
|
||||
implementation.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ->
|
||||
continue@loop
|
||||
context.state.jvmDefaultMode.isCompatibility -> {
|
||||
val defaultImpl = createDefaultImpl(function)
|
||||
defaultImpl.bridgeViaAccessorTo(function)
|
||||
}
|
||||
!implementation.hasJvmDefault() -> {
|
||||
val defaultImpl = createDefaultImpl(function)
|
||||
context.declarationFactory.getDefaultImplsFunction(implementation).also {
|
||||
defaultImpl.bridgeToStatic(it)
|
||||
}
|
||||
}
|
||||
context.state.jvmDefaultMode.isCompatibility -> {
|
||||
val defaultImpl = createDefaultImpl(function)
|
||||
defaultImpl.bridgeViaAccessorTo(function)
|
||||
}
|
||||
// else -> Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
interface I {
|
||||
fun foo(x: String = "OK"): String = x
|
||||
}
|
||||
|
||||
interface J : I
|
||||
|
||||
object O : J
|
||||
|
||||
fun box(): String = O.foo()
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// FILE: I.kt
|
||||
|
||||
interface I {
|
||||
fun foo(x: String = "OK"): String = x
|
||||
}
|
||||
|
||||
// FILE: J.kt
|
||||
|
||||
interface J : I
|
||||
|
||||
// @I$DefaultImpls.class:
|
||||
// 1 foo\$default
|
||||
|
||||
// @J$DefaultImpls.class:
|
||||
// 0 foo\$default
|
||||
+5
@@ -15104,6 +15104,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/defaultArgsViaAnonymousObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedFunctionWithDefaultParameters.kt")
|
||||
public void testInheritedFunctionWithDefaultParameters() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedFunctionWithDefaultParameters.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedJvmDefault.kt")
|
||||
public void testInheritedJvmDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedJvmDefault.kt");
|
||||
|
||||
@@ -1560,6 +1560,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/defaultArguments"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedInterfaceFunction.kt")
|
||||
public void testInheritedInterfaceFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/defaultArguments/inheritedInterfaceFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt11962.kt")
|
||||
public void testKt11962() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/defaultArguments/kt11962.kt");
|
||||
|
||||
+5
@@ -15104,6 +15104,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/defaultArgsViaAnonymousObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedFunctionWithDefaultParameters.kt")
|
||||
public void testInheritedFunctionWithDefaultParameters() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedFunctionWithDefaultParameters.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedJvmDefault.kt")
|
||||
public void testInheritedJvmDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedJvmDefault.kt");
|
||||
|
||||
+5
@@ -13954,6 +13954,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/defaultArgsViaAnonymousObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedFunctionWithDefaultParameters.kt")
|
||||
public void testInheritedFunctionWithDefaultParameters() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedFunctionWithDefaultParameters.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedJvmDefault.kt")
|
||||
public void testInheritedJvmDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedJvmDefault.kt");
|
||||
|
||||
+5
@@ -13954,6 +13954,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/defaultArgsViaAnonymousObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedFunctionWithDefaultParameters.kt")
|
||||
public void testInheritedFunctionWithDefaultParameters() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedFunctionWithDefaultParameters.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedJvmDefault.kt")
|
||||
public void testInheritedJvmDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedJvmDefault.kt");
|
||||
|
||||
+5
@@ -1515,6 +1515,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/defaultArguments"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedInterfaceFunction.kt")
|
||||
public void testInheritedInterfaceFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/defaultArguments/inheritedInterfaceFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt11962.kt")
|
||||
public void testKt11962() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/defaultArguments/kt11962.kt");
|
||||
|
||||
Reference in New Issue
Block a user