Fix data class equals codegen for type parameters with interface bounds

#KT-24474 Fixed
This commit is contained in:
Alexander Udalov
2018-05-18 12:18:35 +02:00
parent 542b2abafa
commit e7f6ac1e50
6 changed files with 45 additions and 12 deletions
@@ -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);
}
@@ -0,0 +1,9 @@
interface A
data class B<out T : A>(val a: T)
fun box(): String {
val b1 = B(object : A {})
val b2 = B(object : A {})
return if (b1.equals(b2)) "Fail" else "OK"
}
@@ -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")
@@ -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")
@@ -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")
@@ -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")