From c959b271a40ac3cbf49c617962bf421fa6071815 Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Wed, 24 Mar 2021 17:27:31 +0800 Subject: [PATCH] Override "hashCode" and "equals" for Getter and Setter to fix KT-13490 --- .../bound/equals/propertyAccessors.kt | 57 ++++++++++++++----- .../reflect/jvm/internal/KPropertyImpl.kt | 12 ++++ 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/compiler/testData/codegen/box/callableReference/bound/equals/propertyAccessors.kt b/compiler/testData/codegen/box/callableReference/bound/equals/propertyAccessors.kt index 6a1ff39ab3b..9235e7d3130 100644 --- a/compiler/testData/codegen/box/callableReference/bound/equals/propertyAccessors.kt +++ b/compiler/testData/codegen/box/callableReference/bound/equals/propertyAccessors.kt @@ -8,30 +8,57 @@ // WITH_REFLECT import kotlin.reflect.KMutableProperty1 +import kotlin.reflect.KMutableProperty2 import kotlin.reflect.full.* class C { var prop = 42 + var String.prop: Int + get() = 42 + set(value) {} } -val C_propReflect = C::class.memberProperties.find { it.name == "prop" } as? KMutableProperty1 ?: throw AssertionError() -val C_prop = C::prop val cProp = C()::prop +val C_prop = C::prop +val C_propReflect = C::class.memberProperties.find { it.name == "prop" } as? KMutableProperty1 ?: throw AssertionError() +val C_extPropReflect = C::class.memberExtensionProperties.find { it.name == "prop" } as? KMutableProperty2 ?: throw AssertionError() fun box() = - when { - C_prop.getter != C_prop.getter -> "C_prop.getter != C_prop.getter" - C_propReflect.getter != C_propReflect.getter -> "C_propReflect.getter != C_propReflect.getter" - cProp.getter != cProp.getter -> "cProp.getter != cProp.getter" + when { + C_prop.getter != C_propReflect.getter -> "C_prop.getter != C_propReflect.getter" + C_prop.setter != C_propReflect.setter -> "C_prop.setter != C_propReflect.setter" + C_propReflect.getter != C_prop.getter -> "C_propReflect.getter != C_prop.getter" + C_propReflect.setter != C_prop.setter -> "C_propReflect.setter != C_prop.setter" - cProp.getter == C_prop.getter -> "cProp.getter == C_prop.getter" - C_prop.getter == cProp.getter -> "C_prop.getter == cProp.getter" - cProp.getter == C_propReflect.getter -> "cProp.getter == C_propReflect.getter" - C_propReflect.getter == cProp.getter -> "C_propReflect.getter == cProp.getter" + // reflexive test of acessors of KProperty0, KProperty1, KProperty2 + cProp.getter != cProp.getter -> "cProp.getter != cProp.getter" + cProp.setter != cProp.setter -> "cProp.setter != cProp.setter" + C_prop.getter != C_prop.getter -> "C_prop.getter != C_prop.getter" + C_prop.setter != C_prop.setter -> "C_prop.setter != C_prop.setter" + C_propReflect.getter != C_propReflect.getter -> "C_propReflect.getter != C_propReflect.getter" + C_propReflect.setter != C_propReflect.setter -> "C_propReflect.setter != C_propReflect.setter" + C_extPropReflect.getter != C_extPropReflect.getter -> "C_extPropReflect.getter != C_extPropReflect.getter" + C_extPropReflect.setter != C_extPropReflect.setter -> "C_extPropReflect.setter != C_extPropReflect.setter" - // TODO https://youtrack.jetbrains.com/issue/KT-13490 - // cProp.getter != C()::prop.getter -> "cProp.getter != C()::prop.getter" - // cProp.setter != C()::prop.setter -> "cProp.setter != C()::prop.setter" + // acessors of KProperty0, Kproperty1 and Kproperty2 are not equal to each other + cProp.getter == C_prop.getter -> "cProp.getter == C_prop.getter" + cProp.setter == C_prop.setter -> "cProp.setter == C_prop.setter" + C_prop.getter == cProp.getter -> "C_prop.getter == cProp.getter" + C_prop.setter == cProp.setter -> "C_prop.setter == cProp.setter" + cProp.getter == C_propReflect.getter -> "cProp.getter == C_propReflect.getter" + cProp.setter == C_propReflect.setter -> "cProp.setter == C_propReflect.setter" + C_propReflect.getter == cProp.getter -> "C_propReflect.getter == cProp.getter" + C_propReflect.setter == cProp.setter -> "C_propReflect.setter == cProp.setter" - else -> "OK" - } + cProp.getter == C_extPropReflect.getter -> "cProp.getter == C_extPropReflect.getter" + cProp.setter == C_extPropReflect.setter -> "cProp.setter == C_extPropReflect.setter" + C_extPropReflect.getter == cProp.getter -> "C_extPropReflect.getter == cProp.getter" + C_extPropReflect.setter == cProp.setter -> "C_extPropReflect.setter == cProp.setter" + + C_prop.getter == C_extPropReflect.getter -> "C_prop.getter == C_extPropReflect.getter" + C_prop.setter == C_extPropReflect.setter -> "C_prop.setter == C_extPropReflect.setter" + C_extPropReflect.getter == C_prop.getter -> "C_extPropReflect.getter == C_prop.getter" + C_extPropReflect.setter == C_prop.setter -> "C_extPropReflect.setter == C_prop.setter" + + else -> "OK" + } diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt index c5b86e06af6..234f59f18ca 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt @@ -157,6 +157,12 @@ internal abstract class KPropertyImpl private constructor( } override fun toString(): String = "getter of $property" + + override fun equals(other: Any?): Boolean = + other is Getter<*> && property == other.property + + override fun hashCode(): Int = + property.hashCode() } abstract class Setter : Accessor(), KMutableProperty.Setter { @@ -172,6 +178,12 @@ internal abstract class KPropertyImpl private constructor( } override fun toString(): String = "setter of $property" + + override fun equals(other: Any?): Boolean = + other is Setter<*> && property == other.property + + override fun hashCode(): Int = + property.hashCode() } companion object {