JVM/JVM_IR: fix mapping of KClass in annotation classes
* JVM incorrectly mapped T<KClass<...>> to T<Class<...>> because the annotation-ness of the type mapping mode was inherited one level down into a generic signature independent of T * JVM_IR was even worse as it did not use VALUE_FOR_ANNOTATION at all, mapping T<T<KClass<...>> to T<T<Class<...>> as well. The correct behavior is to map KClass to Class only at top level or as an argument of Array.
This commit is contained in:
+1
-1
@@ -137,7 +137,7 @@ class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapperBas
|
||||
arrayElementType = AsmTypes.OBJECT_TYPE
|
||||
sw?.writeClass(arrayElementType)
|
||||
} else {
|
||||
arrayElementType = mapType(memberType, mode.toGenericArgumentMode(variance), sw)
|
||||
arrayElementType = mapType(memberType, mode.toGenericArgumentMode(variance, ofArray = true), sw)
|
||||
}
|
||||
sw?.writeArrayEnd()
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
annotation class Ann(val arg: Array<out KClass<out KClass<*>>>)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
annotation class Ann(val arg: KClass<out KClass<*>>)
|
||||
|
||||
// method: Ann::arg
|
||||
// jvm signature: ()Ljava/lang/Class;
|
||||
// generic signature: ()Ljava/lang/Class<+Lkotlin/reflect/KClass<*>;>;
|
||||
+5
@@ -170,6 +170,11 @@ public class IrWriteSignatureTestGenerated extends AbstractIrWriteSignatureTest
|
||||
public void testKClassInt() throws Exception {
|
||||
runTest("compiler/testData/writeSignature/annotations/kClassInt.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kClassOfKClass.kt")
|
||||
public void testKClassOfKClass() throws Exception {
|
||||
runTest("compiler/testData/writeSignature/annotations/kClassOfKClass.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/writeSignature/callableReference")
|
||||
|
||||
+5
@@ -169,6 +169,11 @@ public class WriteSignatureTestGenerated extends AbstractWriteSignatureTest {
|
||||
public void testKClassInt() throws Exception {
|
||||
runTest("compiler/testData/writeSignature/annotations/kClassInt.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kClassOfKClass.kt")
|
||||
public void testKClassOfKClass() throws Exception {
|
||||
runTest("compiler/testData/writeSignature/annotations/kClassOfKClass.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/writeSignature/callableReference")
|
||||
|
||||
@@ -68,7 +68,7 @@ class TypeMappingMode private constructor(
|
||||
)
|
||||
|
||||
/**
|
||||
* kotlin.reflect.KClass mapped to java.lang.Class
|
||||
* kotlin.reflect.KClass mapped to java.lang.Class when at top level or in an array;
|
||||
* primitive types and inline class types are not boxed because types in annotations cannot be nullable
|
||||
* Other types mapped as DEFAULT
|
||||
*/
|
||||
@@ -77,7 +77,7 @@ class TypeMappingMode private constructor(
|
||||
isForAnnotationParameter = true,
|
||||
needPrimitiveBoxing = false,
|
||||
needInlineClassWrapping = false,
|
||||
genericArgumentMode = TypeMappingMode(isForAnnotationParameter = true, genericArgumentMode = GENERIC_ARGUMENT)
|
||||
genericArgumentMode = GENERIC_ARGUMENT
|
||||
)
|
||||
|
||||
|
||||
@@ -89,48 +89,37 @@ class TypeMappingMode private constructor(
|
||||
@JvmStatic
|
||||
fun getOptimalModeForValueParameter(
|
||||
type: KotlinType
|
||||
) = getOptimalModeForSignaturePart(type, isForAnnotationParameter = false, canBeUsedInSupertypePosition = true)
|
||||
) = getOptimalModeForSignaturePart(type, canBeUsedInSupertypePosition = true)
|
||||
|
||||
@JvmStatic
|
||||
fun getOptimalModeForReturnType(
|
||||
type: KotlinType,
|
||||
isAnnotationMethod: Boolean
|
||||
) = getOptimalModeForSignaturePart(type, isForAnnotationParameter = isAnnotationMethod, canBeUsedInSupertypePosition = false)
|
||||
) = if (isAnnotationMethod) VALUE_FOR_ANNOTATION else getOptimalModeForSignaturePart(type, canBeUsedInSupertypePosition = false)
|
||||
|
||||
private fun getOptimalModeForSignaturePart(
|
||||
type: KotlinType,
|
||||
isForAnnotationParameter: Boolean,
|
||||
canBeUsedInSupertypePosition: Boolean
|
||||
): TypeMappingMode {
|
||||
private fun getOptimalModeForSignaturePart(type: KotlinType, canBeUsedInSupertypePosition: Boolean): TypeMappingMode {
|
||||
if (type.arguments.isEmpty()) return DEFAULT
|
||||
|
||||
if (type.isInlineClassType() && shouldUseUnderlyingType(type)) {
|
||||
val underlyingType = computeUnderlyingType(type)
|
||||
if (underlyingType != null) {
|
||||
return getOptimalModeForSignaturePart(
|
||||
underlyingType, isForAnnotationParameter, canBeUsedInSupertypePosition
|
||||
).dontWrapInlineClassesMode()
|
||||
return getOptimalModeForSignaturePart(underlyingType, canBeUsedInSupertypePosition).dontWrapInlineClassesMode()
|
||||
}
|
||||
}
|
||||
|
||||
val contravariantArgumentMode =
|
||||
if (!canBeUsedInSupertypePosition)
|
||||
TypeMappingMode(
|
||||
isForAnnotationParameter = isForAnnotationParameter,
|
||||
skipDeclarationSiteWildcards = false,
|
||||
skipDeclarationSiteWildcardsIfPossible = true
|
||||
)
|
||||
TypeMappingMode(skipDeclarationSiteWildcards = false, skipDeclarationSiteWildcardsIfPossible = true)
|
||||
else
|
||||
null
|
||||
|
||||
val invariantArgumentMode =
|
||||
if (canBeUsedInSupertypePosition)
|
||||
getOptimalModeForSignaturePart(type, isForAnnotationParameter, canBeUsedInSupertypePosition = false)
|
||||
getOptimalModeForSignaturePart(type, canBeUsedInSupertypePosition = false)
|
||||
else
|
||||
null
|
||||
|
||||
return TypeMappingMode(
|
||||
isForAnnotationParameter = isForAnnotationParameter,
|
||||
skipDeclarationSiteWildcards = !canBeUsedInSupertypePosition,
|
||||
skipDeclarationSiteWildcardsIfPossible = true,
|
||||
genericContravariantArgumentMode = contravariantArgumentMode,
|
||||
@@ -153,8 +142,8 @@ class TypeMappingMode private constructor(
|
||||
)
|
||||
}
|
||||
|
||||
fun toGenericArgumentMode(effectiveVariance: Variance): TypeMappingMode =
|
||||
when (effectiveVariance) {
|
||||
fun toGenericArgumentMode(effectiveVariance: Variance, ofArray: Boolean = false): TypeMappingMode =
|
||||
if (ofArray && isForAnnotationParameter) this else when (effectiveVariance) {
|
||||
Variance.IN_VARIANCE -> genericContravariantArgumentMode ?: this
|
||||
Variance.INVARIANT -> genericInvariantArgumentMode ?: this
|
||||
else -> genericArgumentMode ?: this
|
||||
|
||||
@@ -121,8 +121,8 @@ fun <T : Any> mapType(
|
||||
descriptorTypeWriter?.writeArrayType()
|
||||
|
||||
arrayElementType = mapType(
|
||||
memberType, factory, mode.toGenericArgumentMode(memberProjection.projectionKind), typeMappingConfiguration,
|
||||
descriptorTypeWriter, writeGenericType
|
||||
memberType, factory, mode.toGenericArgumentMode(memberProjection.projectionKind, ofArray = true),
|
||||
typeMappingConfiguration, descriptorTypeWriter, writeGenericType
|
||||
)
|
||||
|
||||
descriptorTypeWriter?.writeArrayEnd()
|
||||
|
||||
Reference in New Issue
Block a user