From 5048471835ce0bc6e446a2761cafd984b33a668f Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Tue, 6 Oct 2020 13:10:50 +0200 Subject: [PATCH] Properly check default kind on inheriting from old DefaultImpls scheme --- .../kotlin/codegen/FunctionCodegen.java | 3 +- ...mpileKotlinAgainstKotlinTestGenerated.java | 5 ++++ .../jvm/annotations/jvmAnnotationUtil.kt | 2 +- .../jvm8/defaults/interop/newAndOldSchemes.kt | 13 +++++--- .../defaults/interop/newAndOldSchemes3.kt | 30 +++++++++++++++++++ ...mpileKotlinAgainstKotlinTestGenerated.java | 5 ++++ ...mpileKotlinAgainstKotlinTestGenerated.java | 5 ++++ .../ir/JvmIrAgainstOldBoxTestGenerated.java | 5 ++++ .../ir/JvmOldAgainstIrBoxTestGenerated.java | 5 ++++ 9 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes3.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 76bd9058124..0e0cc818355 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -1679,7 +1679,8 @@ public class FunctionCodegen { assert isInterface(containingDeclaration) : "'processInterfaceMethod' method should be called only for interfaces, but: " + containingDeclaration; - if (JvmAnnotationUtilKt.isCompiledToJvmDefault(memberDescriptor, mode)) { + // Fake overrides in interfaces should be expanded to implementation to make proper default check + if (JvmAnnotationUtilKt.checkIsImplementationCompiledToJvmDefault(memberDescriptor, mode)) { return (kind != OwnerKind.DEFAULT_IMPLS && !isSynthetic) || (kind == OwnerKind.DEFAULT_IMPLS && (isSynthetic || //TODO: move synthetic method generation into interface diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/FirCompileKotlinAgainstKotlinTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/FirCompileKotlinAgainstKotlinTestGenerated.java index 8ae42457ca5..4ea8ee89229 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/FirCompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/FirCompileKotlinAgainstKotlinTestGenerated.java @@ -563,6 +563,11 @@ public class FirCompileKotlinAgainstKotlinTestGenerated extends AbstractFirCompi runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes2Compatibility.kt"); } + @TestMetadata("newAndOldSchemes3.kt") + public void testNewAndOldSchemes3() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes3.kt"); + } + @TestMetadata("newSchemeWithJvmDefault.kt") public void testNewSchemeWithJvmDefault() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newSchemeWithJvmDefault.kt"); diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/annotations/jvmAnnotationUtil.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/annotations/jvmAnnotationUtil.kt index 052e0b5c26b..91eca15f61d 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/annotations/jvmAnnotationUtil.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/annotations/jvmAnnotationUtil.kt @@ -61,7 +61,7 @@ fun CallableMemberDescriptor.isCompiledToJvmDefault(jvmDefault: JvmDefaultMode): return JvmProtoBufUtil.isNewPlaceForBodyGeneration(clazz.classProto) } -fun FunctionDescriptor.checkIsImplementationCompiledToJvmDefault(jvmDefaultMode: JvmDefaultMode): Boolean { +fun CallableMemberDescriptor.checkIsImplementationCompiledToJvmDefault(jvmDefaultMode: JvmDefaultMode): Boolean { val actualImplementation = (if (kind.isReal) this else findImplementationFromInterface(this)) ?: error("Can't find actual implementation for $this") diff --git a/compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes.kt b/compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes.kt index f15a84c1258..6f8c16cb5db 100644 --- a/compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes.kt +++ b/compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes.kt @@ -16,16 +16,21 @@ interface KInterface2 : KInterface { override fun superCall() = super.superCall() } -class Foo: KInterface2 { - fun superCall2() = super.superCall() +interface KInterface3 : KInterface2 { + +} + +class Foo: KInterface3 { + fun superCall2() = super.superCall() } fun box(): String { var result = Foo().call() if (result[1] != "KInterface\$DefaultImpls.call") return "fail 1: ${result[1]}" if (result[2] != "KInterface2\$DefaultImpls.call") return "fail 2: ${result[2]}" - if (result[3] != "Foo.call") return "fail 3: ${result[3]}" - if (result[4] != "MainKt.box") return "fail 4: ${result[4]}" + if (result[3] != "KInterface3\$DefaultImpls.call") return "fail 3: ${result[3]}" + if (result[4] != "Foo.call") return "fail 4: ${result[4]}" + if (result[5] != "MainKt.box") return "fail 5: ${result[5]}" result = Foo().superCall2() if (result[1] != "KInterface\$DefaultImpls.superCall") return "fail 1: ${result[1]}" diff --git a/compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes3.kt b/compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes3.kt new file mode 100644 index 00000000000..309ec073a8e --- /dev/null +++ b/compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes3.kt @@ -0,0 +1,30 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// FULL_JDK +// FILE: 1.kt +// !JVM_DEFAULT_MODE: disable +interface KInterface { + fun call(): List { + return Thread.currentThread().getStackTrace().map { it.className + "." + it.methodName } + } +} + +// FILE: main.kt +// !JVM_DEFAULT_MODE: all +// JVM_TARGET: 1.8 +interface KInterface2 : KInterface { + +} + +class Foo: KInterface2 { + +} + +fun box(): String { + var result = Foo().call() + if (result[1] != "KInterface\$DefaultImpls.call") return "fail 1: ${result[1]}" + if (result[2] != "KInterface2\$DefaultImpls.call") return "fail 2: ${result[2]}" + if (result[3] != "Foo.call") return "fail 3: ${result[3]}" + if (result[4] != "MainKt.box") return "fail 4: ${result[4]}" + + return "OK" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java index e20e3f142c0..0246ae15562 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java @@ -568,6 +568,11 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes2Compatibility.kt"); } + @TestMetadata("newAndOldSchemes3.kt") + public void testNewAndOldSchemes3() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes3.kt"); + } + @TestMetadata("newSchemeWithJvmDefault.kt") public void testNewSchemeWithJvmDefault() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newSchemeWithJvmDefault.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java index 36f3025d839..c21b4e3bb1d 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java @@ -563,6 +563,11 @@ public class IrCompileKotlinAgainstKotlinTestGenerated extends AbstractIrCompile runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes2Compatibility.kt"); } + @TestMetadata("newAndOldSchemes3.kt") + public void testNewAndOldSchemes3() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes3.kt"); + } + @TestMetadata("newSchemeWithJvmDefault.kt") public void testNewSchemeWithJvmDefault() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newSchemeWithJvmDefault.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxTestGenerated.java index a938377fcf6..83a339ce840 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxTestGenerated.java @@ -563,6 +563,11 @@ public class JvmIrAgainstOldBoxTestGenerated extends AbstractJvmIrAgainstOldBoxT runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes2Compatibility.kt"); } + @TestMetadata("newAndOldSchemes3.kt") + public void testNewAndOldSchemes3() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes3.kt"); + } + @TestMetadata("newSchemeWithJvmDefault.kt") public void testNewSchemeWithJvmDefault() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newSchemeWithJvmDefault.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxTestGenerated.java index a75fed3a00d..8669e3f539c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxTestGenerated.java @@ -563,6 +563,11 @@ public class JvmOldAgainstIrBoxTestGenerated extends AbstractJvmOldAgainstIrBoxT runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes2Compatibility.kt"); } + @TestMetadata("newAndOldSchemes3.kt") + public void testNewAndOldSchemes3() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newAndOldSchemes3.kt"); + } + @TestMetadata("newSchemeWithJvmDefault.kt") public void testNewSchemeWithJvmDefault() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newSchemeWithJvmDefault.kt");