From e7f6ac1e500c6f8db024a879a4272aa9acf57c8b Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 18 May 2018 12:18:35 +0200 Subject: [PATCH] Fix data class equals codegen for type parameters with interface bounds #KT-24474 Fixed --- .../codegen/ImplementationBodyCodegen.java | 28 +++++++++++-------- .../equals/typeParameterWithInterfaceBound.kt | 9 ++++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 ++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 ++++ .../LightAnalysisModeTestGenerated.java | 5 ++++ .../semantics/JsCodegenBoxTestGenerated.java | 5 ++++ 6 files changed, 45 insertions(+), 12 deletions(-) create mode 100644 compiler/testData/codegen/box/dataClasses/equals/typeParameterWithInterfaceBound.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index 14fec179f65..e2ce0e71dd4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -558,7 +558,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.store(2, OBJECT_TYPE); for (PropertyDescriptor propertyDescriptor : properties) { - Type asmType = typeMapper.mapType(propertyDescriptor); + KotlinType type = propertyDescriptor.getType(); + Type asmType = typeMapper.mapType(type); Type thisPropertyType = genPropertyOnStack(iv, context, propertyDescriptor, ImplementationBodyCodegen.this.classAsmType, 0); StackValue.coerce(thisPropertyType, asmType, iv); @@ -579,18 +580,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { StackValue value = StackValue.cmp(KtTokens.EQEQ, asmType, StackValue.onStack(asmType), StackValue.onStack(asmType)); value.put(Type.BOOLEAN_TYPE, iv); } - else if (TypeUtils.isNullableType(propertyDescriptor.getType())) { - StackValue value = - genEqualsForExpressionsOnStack(KtTokens.EQEQ, StackValue.onStack(asmType), StackValue.onStack(asmType)); - value.put(Type.BOOLEAN_TYPE, iv); - } else { - Type owner = - DescriptorUtils.isInterface(propertyDescriptor.getType().getConstructor().getDeclarationDescriptor()) - ? AsmTypes.OBJECT_TYPE - : asmType; - iv.invokevirtual(owner.getInternalName(), "equals", - Type.getMethodDescriptor(Type.BOOLEAN_TYPE, AsmTypes.OBJECT_TYPE), false); + if (TypeUtils.isNullableType(type)) { + StackValue value = + genEqualsForExpressionsOnStack(KtTokens.EQEQ, StackValue.onStack(asmType), StackValue.onStack(asmType)); + value.put(Type.BOOLEAN_TYPE, iv); + } + else { + ClassifierDescriptor classifier = type.getConstructor().getDeclarationDescriptor(); + Type owner = + !(classifier instanceof ClassDescriptor) || DescriptorUtils.isInterface(classifier) + ? AsmTypes.OBJECT_TYPE + : asmType; + iv.invokevirtual(owner.getInternalName(), "equals", + Type.getMethodDescriptor(Type.BOOLEAN_TYPE, AsmTypes.OBJECT_TYPE), false); + } } iv.ifeq(ne); } diff --git a/compiler/testData/codegen/box/dataClasses/equals/typeParameterWithInterfaceBound.kt b/compiler/testData/codegen/box/dataClasses/equals/typeParameterWithInterfaceBound.kt new file mode 100644 index 00000000000..e590a0b50ce --- /dev/null +++ b/compiler/testData/codegen/box/dataClasses/equals/typeParameterWithInterfaceBound.kt @@ -0,0 +1,9 @@ +interface A + +data class B(val a: T) + +fun box(): String { + val b1 = B(object : A {}) + val b2 = B(object : A {}) + return if (b1.equals(b2)) "Fail" else "OK" +} diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index a04ff4b57f1..cab217aa19e 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -7941,6 +7941,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes public void testSameinstance() throws Exception { runTest("compiler/testData/codegen/box/dataClasses/equals/sameinstance.kt"); } + + @TestMetadata("typeParameterWithInterfaceBound.kt") + public void testTypeParameterWithInterfaceBound() throws Exception { + runTest("compiler/testData/codegen/box/dataClasses/equals/typeParameterWithInterfaceBound.kt"); + } } @TestMetadata("compiler/testData/codegen/box/dataClasses/hashCode") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index d2509d196f8..32851c2c1e7 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -7941,6 +7941,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testSameinstance() throws Exception { runTest("compiler/testData/codegen/box/dataClasses/equals/sameinstance.kt"); } + + @TestMetadata("typeParameterWithInterfaceBound.kt") + public void testTypeParameterWithInterfaceBound() throws Exception { + runTest("compiler/testData/codegen/box/dataClasses/equals/typeParameterWithInterfaceBound.kt"); + } } @TestMetadata("compiler/testData/codegen/box/dataClasses/hashCode") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index a3dea99c68a..3ea8d5accc0 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -7941,6 +7941,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes public void testSameinstance() throws Exception { runTest("compiler/testData/codegen/box/dataClasses/equals/sameinstance.kt"); } + + @TestMetadata("typeParameterWithInterfaceBound.kt") + public void testTypeParameterWithInterfaceBound() throws Exception { + runTest("compiler/testData/codegen/box/dataClasses/equals/typeParameterWithInterfaceBound.kt"); + } } @TestMetadata("compiler/testData/codegen/box/dataClasses/hashCode") diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 5ec2f0dc4a8..5d64fdd7cb4 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -6523,6 +6523,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { public void testSameinstance() throws Exception { runTest("compiler/testData/codegen/box/dataClasses/equals/sameinstance.kt"); } + + @TestMetadata("typeParameterWithInterfaceBound.kt") + public void testTypeParameterWithInterfaceBound() throws Exception { + runTest("compiler/testData/codegen/box/dataClasses/equals/typeParameterWithInterfaceBound.kt"); + } } @TestMetadata("compiler/testData/codegen/box/dataClasses/hashCode")