diff --git a/compiler/testData/codegen/reflection/classLoaders/kTypeEquality.kt b/compiler/testData/codegen/reflection/classLoaders/kTypeEquality.kt new file mode 100644 index 00000000000..3dc7da9e475 --- /dev/null +++ b/compiler/testData/codegen/reflection/classLoaders/kTypeEquality.kt @@ -0,0 +1,25 @@ +package test + +import kotlin.reflect.* +import kotlin.reflect.full.* +import kotlin.test.* + +class K { + fun getType() = typeOf>() +} + +class Test { + fun kClass(): Any = K::class + + fun KClass<*>.invokeGetType() = + java.declaredMethods.single { it.name == "getType" }.invoke(java.getDeclaredConstructor().newInstance()) as KType + + fun doTest(k1: KClass<*>, k2: KClass<*>) { + assertNotEquals(k1, k2) + + val type1 = k1.invokeGetType() + val type2 = k2.invokeGetType() + assertNotEquals((type1.arguments[0].type)?.classifier, (type2.arguments[0].type)?.classifier) + assertNotEquals(type1, type2) + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ReflectionClassLoaderTest.kt b/compiler/tests/org/jetbrains/kotlin/codegen/ReflectionClassLoaderTest.kt index 1322a17f27a..9a6d0ecdfe8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ReflectionClassLoaderTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ReflectionClassLoaderTest.kt @@ -77,4 +77,17 @@ class ReflectionClassLoaderTest : CodegenTestCase() { ChildClassLoader(parent) ) } + + fun testKTypeEquality() { + /* + * Check that typeOf>() when clz is loaded by different classloaders + * differs in both its `equals` and its `classifier`. + * It is important in the face of KType caching + */ + loadFile("$prefix/kTypeEquality.kt") + doTest( + createClassLoader(), + createClassLoader() + ) + } } diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KTypeImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KTypeImpl.kt index 5dd3fe793d4..e147ae76940 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KTypeImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KTypeImpl.kt @@ -39,7 +39,6 @@ internal class KTypeImpl( val type: KotlinType, computeJavaType: (() -> Type)? = null ) : KTypeBase { - @Suppress("UNCHECKED_CAST") private val computeJavaType = computeJavaType as? ReflectProperties.LazySoftVal ?: computeJavaType?.let(ReflectProperties::lazySoft) @@ -126,10 +125,10 @@ internal class KTypeImpl( } override fun equals(other: Any?) = - other is KTypeImpl && type == other.type + other is KTypeImpl && type == other.type && classifier == other.classifier && arguments == other.arguments override fun hashCode() = - type.hashCode() + (31 * ((31 * type.hashCode()) + classifier.hashCode())) + arguments.hashCode() override fun toString() = ReflectionObjectRenderer.renderType(type)