diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index d4c5b3707ff..c8d6d6df342 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -41,7 +41,6 @@ import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.incremental.components.NoLookupLocation; import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.load.java.JvmAbi; -import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor; import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; @@ -1326,7 +1325,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { for (Map.Entry entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) { FunctionDescriptor interfaceFun = entry.getKey(); //skip java 8 default methods - if (!(interfaceFun instanceof JavaCallableMemberDescriptor)) { + if (!CodegenUtilKt.isDefinitelyNotDefaultImplsMethod(interfaceFun)) { generateDelegationToDefaultImpl(interfaceFun, entry.getValue()); } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt index 89ca879ae07..7dce196498c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.DelegationToDefaultImpls import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.serialization.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME import org.jetbrains.org.objectweb.asm.MethodVisitor import org.jetbrains.org.objectweb.asm.Opcodes.* import java.util.* @@ -77,8 +78,8 @@ class InterfaceImplBodyCodegen( val implementation = findImplementationFromInterface(memberDescriptor) ?: continue - // If implementation is located in a Java interface, it will be inherited via normal Java rules - if (implementation is JavaMethodDescriptor) continue + // If implementation is a default interface method (JVM 8 only) + if (implementation.isDefinitelyNotDefaultImplsMethod()) continue // We create a copy of the function with kind = DECLARATION so that FunctionCodegen will generate its body val copy = memberDescriptor.copy(memberDescriptor.containingDeclaration, Modality.OPEN, memberDescriptor.visibility, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt index a7cbb844630..6069283db99 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt @@ -23,16 +23,19 @@ import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo import org.jetbrains.kotlin.load.java.JvmAbi +import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtObjectDeclaration import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.serialization.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils @@ -182,4 +185,7 @@ fun sortTopLevelClassesAndPrepareContextForSealedClasses( } sortedDescriptors.mapTo(result) { descriptorToPsi[it]!! } return result -} \ No newline at end of file +} + +fun CallableMemberDescriptor.isDefinitelyNotDefaultImplsMethod() = + this is JavaCallableMemberDescriptor || this.annotations.hasAnnotation(PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME) diff --git a/compiler/testData/codegen/java8/box/mapRemove/noDefaultImpls.kt b/compiler/testData/codegen/java8/box/mapRemove/noDefaultImpls.kt new file mode 100644 index 00000000000..ba393324638 --- /dev/null +++ b/compiler/testData/codegen/java8/box/mapRemove/noDefaultImpls.kt @@ -0,0 +1,29 @@ +// JVM_TARGET: 1.8 +// FULL_JDK + +// There should be no DefaultImpls method for MutableMap.remove(K;V) +interface A : MutableMap + +class B : A, java.util.AbstractMap() { + override val entries: MutableSet> + get() = java.util.HashSet() +} + +interface C : MutableMap { + override fun remove(key: K, value: V) = true +} + +class D : A, java.util.AbstractMap() { + override val entries: MutableSet> + get() = java.util.HashSet() +} + +fun box(): String { + val x1 = B().remove("1", "2") + if (x1) return "fail 1" + + val x2 = D().remove("3", "4") + if (x1) return "fail 2" + + return "OK" +} diff --git a/compiler/tests-java8/tests/org/jetbrains/kotlin/codegen/BlackBoxWithJava8CodegenTestGenerated.java b/compiler/tests-java8/tests/org/jetbrains/kotlin/codegen/BlackBoxWithJava8CodegenTestGenerated.java index 706388203ec..40c88388395 100644 --- a/compiler/tests-java8/tests/org/jetbrains/kotlin/codegen/BlackBoxWithJava8CodegenTestGenerated.java +++ b/compiler/tests-java8/tests/org/jetbrains/kotlin/codegen/BlackBoxWithJava8CodegenTestGenerated.java @@ -187,6 +187,12 @@ public class BlackBoxWithJava8CodegenTestGenerated extends AbstractBlackBoxCodeg KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/java8/box/mapRemove"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("noDefaultImpls.kt") + public void testNoDefaultImpls() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/mapRemove/noDefaultImpls.kt"); + doTest(fileName); + } + @TestMetadata("readOnlyMap.kt") public void testReadOnlyMap() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/mapRemove/readOnlyMap.kt");