diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmDelegationFilter.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmDelegationFilter.kt index 1f7542afd3a..11d08480873 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmDelegationFilter.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmDelegationFilter.kt @@ -16,20 +16,29 @@ package org.jetbrains.kotlin.resolve.jvm +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.lazy.DelegationFilter +import org.jetbrains.kotlin.serialization.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME object JvmDelegationFilter : DelegationFilter { override fun filter(interfaceMember: CallableMemberDescriptor): Boolean { //We always have only one implementation otherwise it's an error in kotlin and java - return !isJavaDefaultMethod(DescriptorUtils.unwrapFakeOverride(interfaceMember)) + val realMember = DescriptorUtils.unwrapFakeOverride(interfaceMember) + return !isJavaDefaultMethod(realMember) && !isBuiltInMemberMappedToJavaDefault(realMember) } private fun isJavaDefaultMethod(interfaceMember: CallableMemberDescriptor): Boolean { return interfaceMember is JavaMethodDescriptor && interfaceMember.modality != Modality.ABSTRACT } + + private fun isBuiltInMemberMappedToJavaDefault(interfaceMember: CallableMemberDescriptor): Boolean { + return interfaceMember.modality != Modality.ABSTRACT && + KotlinBuiltIns.isBuiltIn(interfaceMember) && + interfaceMember.annotations.hasAnnotation(PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME) + } } diff --git a/compiler/testData/codegen/java8/box/delegationBy/delegationToMap.kt b/compiler/testData/codegen/java8/box/delegationBy/delegationToMap.kt new file mode 100644 index 00000000000..7fef7e87bd1 --- /dev/null +++ b/compiler/testData/codegen/java8/box/delegationBy/delegationToMap.kt @@ -0,0 +1,23 @@ +// FULL_JDK + +class MapWithBadDefaults : HashMap() { + override fun getOrDefault(key: String, defaultValue: String): String { + throw RuntimeException("Shouldn't be executed") + } + + override fun remove(key: String, value: String): Boolean { + throw RuntimeException("Shouldn't be executed") + } +} + + +class Test(map: MutableMap) : MutableMap by map + +fun box(): String { + val test = Test(MapWithBadDefaults()) + test.put("O", "K") + if (!test.containsKey("O")) return "fail 1: can't find value for key 'O'" + if (!test.remove("O", "K")) return "fail 2: entry wasn't removed" + + return test.getOrDefault("absent", "OK") +} \ No newline at end of file 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 abaadbdf6f5..56e88529734 100644 --- a/compiler/tests-java8/tests/org/jetbrains/kotlin/codegen/BlackBoxWithJava8CodegenTestGenerated.java +++ b/compiler/tests-java8/tests/org/jetbrains/kotlin/codegen/BlackBoxWithJava8CodegenTestGenerated.java @@ -140,6 +140,12 @@ public class BlackBoxWithJava8CodegenTestGenerated extends AbstractBlackBoxCodeg doTest(fileName); } + @TestMetadata("delegationToMap.kt") + public void testDelegationToMap() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/delegationBy/delegationToMap.kt"); + doTest(fileName); + } + @TestMetadata("diamond.kt") public void testDiamond() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/delegationBy/diamond.kt");