From efdb4e1d5d0f199a46b1bca8b7509d6223c8f79e Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 22 Jan 2019 09:48:34 +0300 Subject: [PATCH] Fix assertion caused by wrong equality of DescriptorBasedFunctionHandleForJvm In case of the same class defined in different modules they contain different descriptors instances in their scope that might lead to failing assertion in findConcreteSuperDeclaration because there are overridden from different modules It might happen even in the compiler because of different built-in modules defined for sources-module and for dependencies' one ^KT-29320 Fixed --- .../jetbrains/kotlin/codegen/JvmBridgesImpl.kt | 16 ++++++++++++++++ .../testData/codegen/box/jvm8/treeMapBridge.kt | 16 ++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 +++++ .../codegen/LightAnalysisModeTestGenerated.java | 5 +++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++++ 5 files changed, 47 insertions(+) create mode 100644 compiler/testData/codegen/box/jvm8/treeMapBridge.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmBridgesImpl.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmBridgesImpl.kt index 7aeec2c6b91..bcb624e895b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmBridgesImpl.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmBridgesImpl.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.codegen import org.jetbrains.kotlin.backend.common.bridges.* import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmDefaultAnnotation @@ -31,13 +32,28 @@ class DescriptorBasedFunctionHandleForJvm( override val mayBeUsedAsSuperImplementation: Boolean = super.mayBeUsedAsSuperImplementation || descriptor.isJvmDefaultOrPlatformDependent() + private val asmMethod by lazy(LazyThreadSafetyMode.NONE) { + state.typeMapper.mapAsmMethod(descriptor) + } + override val isDeclaration: Boolean = descriptor.kind.isReal || needToGenerateDelegationToDefaultImpls(descriptor) override val mightBeIncorrectCode: Boolean get() = state.classBuilderMode.mightBeIncorrectCode + + override fun hashCode(): Int = descriptor.containerEntityForEqualityAndHashCode().hashCode() + 31 * asmMethod.hashCode() + override fun equals(other: Any?): Boolean { + if (other !is DescriptorBasedFunctionHandleForJvm) return false + + return asmMethod == other.asmMethod && + descriptor.containerEntityForEqualityAndHashCode() == other.descriptor.containerEntityForEqualityAndHashCode() + } } +private fun FunctionDescriptor.containerEntityForEqualityAndHashCode(): Any = + (containingDeclaration as? ClassDescriptor)?.typeConstructor ?: containingDeclaration + private fun CallableMemberDescriptor.isJvmDefaultOrPlatformDependent() = hasJvmDefaultAnnotation() || hasPlatformDependentAnnotation() diff --git a/compiler/testData/codegen/box/jvm8/treeMapBridge.kt b/compiler/testData/codegen/box/jvm8/treeMapBridge.kt new file mode 100644 index 00000000000..c62639b58d0 --- /dev/null +++ b/compiler/testData/codegen/box/jvm8/treeMapBridge.kt @@ -0,0 +1,16 @@ +// TARGET_BACKEND: JVM +// IGNORE_BACKEND: JVM_IR + +// FULL_JDK + +import java.util.* + +private class IntervalTreeMap : TreeMap() + +fun box(): String { + val intervalTreeMap = IntervalTreeMap() + intervalTreeMap.put("123", "356") + + if (!intervalTreeMap.remove("123", "356")) return "fail 1" + return intervalTreeMap.getOrDefault("123", "OK") +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index b7bd27b38e7..0d0876ee56e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -13899,6 +13899,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/jvm8/simpleProperty.kt"); } + @TestMetadata("treeMapBridge.kt") + public void testTreeMapBridge() throws Exception { + runTest("compiler/testData/codegen/box/jvm8/treeMapBridge.kt"); + } + @TestMetadata("compiler/testData/codegen/box/jvm8/defaults") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 8796d31665d..3e2d2baa0df 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -13899,6 +13899,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/jvm8/simpleProperty.kt"); } + @TestMetadata("treeMapBridge.kt") + public void testTreeMapBridge() throws Exception { + runTest("compiler/testData/codegen/box/jvm8/treeMapBridge.kt"); + } + @TestMetadata("compiler/testData/codegen/box/jvm8/defaults") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 72a898c02d1..f6a3c917b41 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -13904,6 +13904,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/jvm8/simpleProperty.kt"); } + @TestMetadata("treeMapBridge.kt") + public void testTreeMapBridge() throws Exception { + runTest("compiler/testData/codegen/box/jvm8/treeMapBridge.kt"); + } + @TestMetadata("compiler/testData/codegen/box/jvm8/defaults") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)