JVM IR: do not use KotlinTypeMapper in IrTypeMapper.mapType
This commit is contained in:
@@ -1433,7 +1433,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
|||||||
private fun hasNothingInNonContravariantPosition(kotlinType: KotlinType): Boolean =
|
private fun hasNothingInNonContravariantPosition(kotlinType: KotlinType): Boolean =
|
||||||
SimpleClassicTypeSystemContext.hasNothingInNonContravariantPosition(kotlinType)
|
SimpleClassicTypeSystemContext.hasNothingInNonContravariantPosition(kotlinType)
|
||||||
|
|
||||||
private fun TypeSystemContext.hasNothingInNonContravariantPosition(type: KotlinTypeMarker): Boolean {
|
fun TypeSystemContext.hasNothingInNonContravariantPosition(type: KotlinTypeMarker): Boolean {
|
||||||
val typeConstructor = type.typeConstructor()
|
val typeConstructor = type.typeConstructor()
|
||||||
|
|
||||||
for (i in 0 until type.argumentsCount()) {
|
for (i in 0 until type.argumentsCount()) {
|
||||||
|
|||||||
+213
-13
@@ -6,40 +6,65 @@
|
|||||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
|
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||||
|
import org.jetbrains.kotlin.builtins.transformSuspendFunctionToRuntimeFunctionType
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||||
|
import org.jetbrains.kotlin.codegen.ClassBuilderMode
|
||||||
|
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||||
|
import org.jetbrains.kotlin.codegen.signature.AsmTypeFactory
|
||||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter
|
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
|
||||||
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
|
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.computeExpandedTypeForInlineClass
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.mapBuiltInType
|
||||||
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||||
|
|
||||||
class IrTypeMapper(private val context: JvmBackendContext) {
|
class IrTypeMapper(private val context: JvmBackendContext) {
|
||||||
val kotlinTypeMapper: KotlinTypeMapper = context.state.typeMapper
|
val kotlinTypeMapper: KotlinTypeMapper = context.state.typeMapper
|
||||||
|
private val typeSystem = IrTypeCheckerContext(context.irBuiltIns)
|
||||||
|
|
||||||
val classBuilderMode get() = kotlinTypeMapper.classBuilderMode
|
val classBuilderMode: ClassBuilderMode
|
||||||
|
get() = kotlinTypeMapper.classBuilderMode
|
||||||
|
|
||||||
fun classInternalName(irClass: IrClass) = kotlinTypeMapper.classInternalName(irClass.descriptor)
|
fun classInternalName(irClass: IrClass): String =
|
||||||
|
context.getLocalClassInfo(irClass)?.internalName
|
||||||
|
?: JvmCodegenUtil.sanitizeNameIfNeeded(computeInternalName(irClass), context.state.languageVersionSettings)
|
||||||
|
|
||||||
fun mapAsmMethod(irFunction: IrFunction) = kotlinTypeMapper.mapAsmMethod(irFunction.descriptor)
|
fun mapAsmMethod(irFunction: IrFunction): Method =
|
||||||
|
kotlinTypeMapper.mapAsmMethod(irFunction.descriptor)
|
||||||
|
|
||||||
fun mapFieldSignature(irField: IrField) =
|
fun mapFieldSignature(irField: IrField) =
|
||||||
kotlinTypeMapper.mapFieldSignature(irField.type.toKotlinType(), irField.descriptor)
|
kotlinTypeMapper.mapFieldSignature(irField.type.toKotlinType(), irField.descriptor)
|
||||||
|
|
||||||
fun mapFunctionName(irReturnTarget: IrReturnTarget, ownerKind: OwnerKind) =
|
fun mapFunctionName(irReturnTarget: IrReturnTarget, ownerKind: OwnerKind): String =
|
||||||
kotlinTypeMapper.mapFunctionName(irReturnTarget.descriptor, ownerKind)
|
kotlinTypeMapper.mapFunctionName(irReturnTarget.descriptor, ownerKind)
|
||||||
|
|
||||||
fun mapImplementationOwner(irDeclaration: IrDeclaration) = kotlinTypeMapper.mapImplementationOwner(irDeclaration.descriptor)
|
fun mapImplementationOwner(irDeclaration: IrDeclaration): Type =
|
||||||
|
kotlinTypeMapper.mapImplementationOwner(irDeclaration.descriptor)
|
||||||
|
|
||||||
fun mapReturnType(irReturnTarget: IrReturnTarget) = kotlinTypeMapper.mapReturnType(irReturnTarget.descriptor)
|
fun mapReturnType(irReturnTarget: IrReturnTarget): Type =
|
||||||
|
kotlinTypeMapper.mapReturnType(irReturnTarget.descriptor)
|
||||||
|
|
||||||
fun mapSignatureSkipGeneric(f: IrFunction, kind: OwnerKind = OwnerKind.IMPLEMENTATION) =
|
fun mapSignatureSkipGeneric(f: IrFunction, kind: OwnerKind = OwnerKind.IMPLEMENTATION): JvmMethodSignature =
|
||||||
kotlinTypeMapper.mapSignatureSkipGeneric(f.descriptor, kind)
|
kotlinTypeMapper.mapSignatureSkipGeneric(f.descriptor, kind)
|
||||||
|
|
||||||
fun mapSignatureWithGeneric(f: IrFunction, kind: OwnerKind) = kotlinTypeMapper.mapSignatureWithGeneric(f.descriptor, kind)
|
fun mapSignatureWithGeneric(f: IrFunction, kind: OwnerKind): JvmMethodGenericSignature =
|
||||||
|
kotlinTypeMapper.mapSignatureWithGeneric(f.descriptor, kind)
|
||||||
|
|
||||||
fun mapToCallableMethod(f: IrFunction, superCall: Boolean, kind: OwnerKind? = null, resolvedCall: ResolvedCall<*>? = null) =
|
fun mapToCallableMethod(f: IrFunction, superCall: Boolean, kind: OwnerKind? = null, resolvedCall: ResolvedCall<*>? = null) =
|
||||||
kotlinTypeMapper.mapToCallableMethod(f.descriptor, superCall, kind, resolvedCall)
|
kotlinTypeMapper.mapToCallableMethod(f.descriptor, superCall, kind, resolvedCall)
|
||||||
@@ -47,13 +72,188 @@ class IrTypeMapper(private val context: JvmBackendContext) {
|
|||||||
fun writeFormalTypeParameters(irParameters: List<IrTypeParameter>, sw: JvmSignatureWriter) =
|
fun writeFormalTypeParameters(irParameters: List<IrTypeParameter>, sw: JvmSignatureWriter) =
|
||||||
kotlinTypeMapper.writeFormalTypeParameters(irParameters.map { it.descriptor }, sw)
|
kotlinTypeMapper.writeFormalTypeParameters(irParameters.map { it.descriptor }, sw)
|
||||||
|
|
||||||
fun boxType(irType: IrType) =
|
fun boxType(irType: IrType): Type =
|
||||||
AsmUtil.boxType(mapType(irType), irType.toKotlinType(), kotlinTypeMapper)
|
AsmUtil.boxType(mapType(irType), irType.toKotlinType(), kotlinTypeMapper)
|
||||||
|
|
||||||
fun mapType(
|
fun mapType(
|
||||||
type: IrType,
|
type: IrType,
|
||||||
mode: TypeMappingMode = TypeMappingMode.DEFAULT,
|
mode: TypeMappingMode = TypeMappingMode.DEFAULT,
|
||||||
sw: JvmSignatureWriter? = null
|
sw: JvmSignatureWriter? = null
|
||||||
): Type =
|
): Type {
|
||||||
kotlinTypeMapper.mapType(type.toKotlinType(), sw, mode)
|
if (type !is IrSimpleType) {
|
||||||
|
val kotlinType = type.originalKotlinType
|
||||||
|
error("Unexpected type: $type (original Kotlin type=$kotlinType of ${kotlinType?.let { it::class }})")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: rewrite this part to produce the correct Type without the fake descriptor
|
||||||
|
if (type.toKotlinType().isSuspendFunctionType) {
|
||||||
|
return kotlinTypeMapper.mapType(
|
||||||
|
transformSuspendFunctionToRuntimeFunctionType(type.toKotlinType(), isReleaseCoroutines = true), sw, mode
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
with(typeSystem) {
|
||||||
|
mapBuiltInType(type, AsmTypeFactory, mode)
|
||||||
|
}?.let { builtInType ->
|
||||||
|
return boxTypeIfNeeded(builtInType, mode.needPrimitiveBoxing).also { asmType ->
|
||||||
|
sw?.writeGenericType(type, asmType, mode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val classifier = type.classifierOrNull?.owner
|
||||||
|
|
||||||
|
when {
|
||||||
|
type.isArray() || type.isNullableArray() -> {
|
||||||
|
val typeArgument = type.arguments.single()
|
||||||
|
val (variance, memberType) = when (typeArgument) {
|
||||||
|
is IrTypeProjection -> Pair(typeArgument.variance, typeArgument.type)
|
||||||
|
is IrStarProjection -> Pair(Variance.OUT_VARIANCE, context.irBuiltIns.anyNType)
|
||||||
|
else -> error("Unsupported type argument: $typeArgument")
|
||||||
|
}
|
||||||
|
|
||||||
|
val arrayElementType: Type
|
||||||
|
sw?.writeArrayType()
|
||||||
|
if (variance == Variance.IN_VARIANCE) {
|
||||||
|
arrayElementType = AsmTypes.OBJECT_TYPE
|
||||||
|
sw?.writeClass(arrayElementType)
|
||||||
|
} else {
|
||||||
|
arrayElementType = mapType(memberType, mode.toGenericArgumentMode(variance), sw)
|
||||||
|
}
|
||||||
|
sw?.writeArrayEnd()
|
||||||
|
|
||||||
|
return AsmUtil.getArrayType(arrayElementType)
|
||||||
|
}
|
||||||
|
|
||||||
|
classifier is IrClass -> {
|
||||||
|
if (classifier.isInline && !mode.needInlineClassWrapping) {
|
||||||
|
val expandedType = typeSystem.computeExpandedTypeForInlineClass(type) as IrType?
|
||||||
|
if (expandedType != null) {
|
||||||
|
return mapType(expandedType, mode.wrapInlineClassesMode(), sw)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val asmType =
|
||||||
|
if (mode.isForAnnotationParameter && type.isKClass()) AsmTypes.JAVA_CLASS_TYPE
|
||||||
|
else Type.getObjectType(classInternalName(classifier))
|
||||||
|
|
||||||
|
sw?.writeGenericType(type, asmType, mode)
|
||||||
|
|
||||||
|
return asmType
|
||||||
|
}
|
||||||
|
|
||||||
|
classifier is IrTypeParameter -> {
|
||||||
|
return mapType(classifier.representativeUpperBound, mode, null).also { asmType ->
|
||||||
|
sw?.writeTypeVariable(classifier.name, asmType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> throw UnsupportedOperationException("Unknown type $type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun computeInternalName(klass: IrClass): String {
|
||||||
|
val className = SpecialNames.safeIdentifier(klass.name).identifier
|
||||||
|
return when (val parent = klass.parent) {
|
||||||
|
is IrPackageFragment -> {
|
||||||
|
val fqName = parent.fqName
|
||||||
|
val prefix = if (fqName.isRoot) "" else fqName.asString().replace('.', '/') + "/"
|
||||||
|
prefix + className
|
||||||
|
}
|
||||||
|
is IrClass -> {
|
||||||
|
computeInternalName(parent) + "$" + className
|
||||||
|
}
|
||||||
|
else -> error(
|
||||||
|
"Local class should have its name computed in InventNamesForLocalClasses: ${klass.fqNameWhenAvailable}\n" +
|
||||||
|
"Ensure that any lowering that transforms elements with local class info (classes, function references, " +
|
||||||
|
"IrTypeOperatorCall for SAM conversions) invokes `copyAttributes` on the transformed element."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copied from KotlinTypeMapper.writeGenericType.
|
||||||
|
private fun JvmSignatureWriter.writeGenericType(type: IrSimpleType, asmType: Type, mode: TypeMappingMode) {
|
||||||
|
if (skipGenericSignature() || hasNothingInNonContravariantPosition(type) || type.arguments.isEmpty()) {
|
||||||
|
writeAsmType(asmType)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val possiblyInnerType = type.buildPossiblyInnerType() ?: error("possiblyInnerType with arguments should not be null")
|
||||||
|
|
||||||
|
val innerTypesAsList = possiblyInnerType.segments()
|
||||||
|
|
||||||
|
val indexOfParameterizedType = innerTypesAsList.indexOfFirst { innerPart -> innerPart.arguments.isNotEmpty() }
|
||||||
|
if (indexOfParameterizedType < 0 || innerTypesAsList.size == 1) {
|
||||||
|
writeClassBegin(asmType)
|
||||||
|
writeGenericArguments(this, possiblyInnerType, mode)
|
||||||
|
} else {
|
||||||
|
val outerType = innerTypesAsList[indexOfParameterizedType]
|
||||||
|
|
||||||
|
writeOuterClassBegin(asmType, mapType(outerType.classifier.defaultType).internalName)
|
||||||
|
writeGenericArguments(this, outerType, mode)
|
||||||
|
|
||||||
|
writeInnerParts(
|
||||||
|
innerTypesAsList,
|
||||||
|
this,
|
||||||
|
mode,
|
||||||
|
indexOfParameterizedType + 1
|
||||||
|
) // inner parts separated by `.`
|
||||||
|
}
|
||||||
|
|
||||||
|
writeClassEnd()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hasNothingInNonContravariantPosition(irType: IrType): Boolean = with(KotlinTypeMapper) {
|
||||||
|
typeSystem.hasNothingInNonContravariantPosition(irType)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun writeInnerParts(
|
||||||
|
innerTypesAsList: List<PossiblyInnerIrType>,
|
||||||
|
sw: JvmSignatureWriter,
|
||||||
|
mode: TypeMappingMode,
|
||||||
|
index: Int
|
||||||
|
) {
|
||||||
|
for (innerPart in innerTypesAsList.subList(index, innerTypesAsList.size)) {
|
||||||
|
sw.writeInnerClass(getJvmShortName(innerPart.classifier))
|
||||||
|
writeGenericArguments(sw, innerPart, mode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copied from KotlinTypeMapper.writeGenericArguments.
|
||||||
|
private fun writeGenericArguments(
|
||||||
|
sw: JvmSignatureWriter,
|
||||||
|
type: PossiblyInnerIrType,
|
||||||
|
mode: TypeMappingMode
|
||||||
|
) {
|
||||||
|
val classifier = type.classifier
|
||||||
|
val parameters = classifier.typeParameters.map(IrTypeParameter::symbol)
|
||||||
|
val arguments = type.arguments
|
||||||
|
|
||||||
|
// TODO: get rid of descriptor here
|
||||||
|
val classDescriptor = classifier.descriptor
|
||||||
|
if (classDescriptor is FunctionClassDescriptor) {
|
||||||
|
if (classDescriptor.hasBigArity ||
|
||||||
|
classDescriptor.functionKind == FunctionClassDescriptor.Kind.KFunction ||
|
||||||
|
classDescriptor.functionKind == FunctionClassDescriptor.Kind.KSuspendFunction
|
||||||
|
) {
|
||||||
|
writeGenericArguments(sw, listOf(arguments.last()), listOf(parameters.last()), mode)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeGenericArguments(sw, arguments, parameters, mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun writeGenericArguments(
|
||||||
|
sw: JvmSignatureWriter,
|
||||||
|
arguments: List<IrTypeArgument>,
|
||||||
|
parameters: List<IrTypeParameterSymbol>,
|
||||||
|
mode: TypeMappingMode
|
||||||
|
) = with(KotlinTypeMapper) {
|
||||||
|
typeSystem.writeGenericArguments(sw, arguments, parameters, mode) { type, sw, mode ->
|
||||||
|
mapType(type as IrType, mode, sw)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun boxTypeIfNeeded(possiblyPrimitiveType: Type, needBoxedType: Boolean): Type =
|
||||||
|
if (needBoxedType) AsmUtil.boxType(possiblyPrimitiveType) else possiblyPrimitiveType
|
||||||
}
|
}
|
||||||
|
|||||||
+54
-4
@@ -5,14 +5,20 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter
|
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrTypeArgument
|
||||||
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
|
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||||
|
import org.jetbrains.kotlin.ir.util.isLocalClass
|
||||||
|
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||||
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
fun IrTypeMapper.mapType(irVariable: IrVariable): Type =
|
fun IrTypeMapper.mapType(irVariable: IrVariable): Type =
|
||||||
@@ -35,3 +41,47 @@ fun IrTypeMapper.mapTypeAsDeclaration(irType: IrType): Type =
|
|||||||
|
|
||||||
fun IrTypeMapper.mapTypeParameter(irType: IrType, sw: JvmSignatureWriter): Type =
|
fun IrTypeMapper.mapTypeParameter(irType: IrType, sw: JvmSignatureWriter): Type =
|
||||||
mapType(irType, TypeMappingMode.GENERIC_ARGUMENT, sw)
|
mapType(irType, TypeMappingMode.GENERIC_ARGUMENT, sw)
|
||||||
|
|
||||||
|
internal fun getJvmShortName(klass: IrClass): String =
|
||||||
|
klass.fqNameWhenAvailable?.toUnsafe()?.let { JavaToKotlinClassMap.mapKotlinToJava(it)?.shortClassName?.asString() }
|
||||||
|
?: SpecialNames.safeIdentifier(klass.name).identifier
|
||||||
|
|
||||||
|
internal class PossiblyInnerIrType(
|
||||||
|
val classifier: IrClass,
|
||||||
|
val arguments: List<IrTypeArgument>,
|
||||||
|
private val outerType: PossiblyInnerIrType?
|
||||||
|
) {
|
||||||
|
fun segments(): List<PossiblyInnerIrType> = outerType?.segments().orEmpty() + this
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun IrSimpleType.buildPossiblyInnerType(): PossiblyInnerIrType? =
|
||||||
|
buildPossiblyInnerType(classOrNull?.owner, 0)
|
||||||
|
|
||||||
|
private fun IrSimpleType.buildPossiblyInnerType(classifier: IrClass?, index: Int): PossiblyInnerIrType? {
|
||||||
|
if (classifier == null) return null
|
||||||
|
|
||||||
|
val toIndex = classifier.typeParameters.size + index
|
||||||
|
if (!classifier.isInner) {
|
||||||
|
assert(toIndex == arguments.size || classifier.isLocalClass()) {
|
||||||
|
"${arguments.size - toIndex} trailing arguments were found in $this type"
|
||||||
|
}
|
||||||
|
|
||||||
|
return PossiblyInnerIrType(classifier, arguments.subList(index, arguments.size), null)
|
||||||
|
}
|
||||||
|
|
||||||
|
val argumentsSubList = arguments.subList(index, toIndex)
|
||||||
|
return PossiblyInnerIrType(
|
||||||
|
classifier, argumentsSubList,
|
||||||
|
buildPossiblyInnerType(classifier.parentAsClass, toIndex)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val IrTypeParameter.representativeUpperBound: IrType
|
||||||
|
get() {
|
||||||
|
assert(superTypes.isNotEmpty()) { "Upper bounds should not be empty: $this" }
|
||||||
|
|
||||||
|
return superTypes.firstOrNull {
|
||||||
|
val irClass = it.classOrNull?.owner ?: return@firstOrNull false
|
||||||
|
irClass.kind != ClassKind.INTERFACE && irClass.kind != ClassKind.ANNOTATION_CLASS
|
||||||
|
} ?: superTypes.first()
|
||||||
|
}
|
||||||
|
|||||||
+10
-3
@@ -5,7 +5,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm.intrinsics
|
package org.jetbrains.kotlin.backend.jvm.intrinsics
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.*
|
import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.codegen.PromisedValue
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.codegen.coerce
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19,10 +22,14 @@ object UnsafeCoerce : IntrinsicMethod() {
|
|||||||
override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? {
|
override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? {
|
||||||
val from = expression.getTypeArgument(0)!!
|
val from = expression.getTypeArgument(0)!!
|
||||||
val to = expression.getTypeArgument(1)!!
|
val to = expression.getTypeArgument(1)!!
|
||||||
require(with(codegen) { typeMapper.mapType(from) == typeMapper.mapType(to) })
|
val fromType = codegen.typeMapper.mapType(from)
|
||||||
|
val toType = codegen.typeMapper.mapType(to)
|
||||||
|
require(fromType == toType) {
|
||||||
|
"Inline class types should have the same representation: $fromType != $toType"
|
||||||
|
}
|
||||||
val arg = expression.getValueArgument(0)!!
|
val arg = expression.getValueArgument(0)!!
|
||||||
val result = arg.accept(codegen, data)
|
val result = arg.accept(codegen, data)
|
||||||
return object : PromisedValue(codegen, codegen.typeMapper.mapType(to), to) {
|
return object : PromisedValue(codegen, toType, to) {
|
||||||
override fun materialize() = result.coerce(from).materialize()
|
override fun materialize() = result.coerce(from).materialize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -84,8 +84,8 @@ private class FunctionNVarargInvokeLowering(var context: JvmBackendContext) : Cl
|
|||||||
symbol = IrValueParameterSymbolImpl(varargParameterDescriptor),
|
symbol = IrValueParameterSymbolImpl(varargParameterDescriptor),
|
||||||
name = Name.identifier("args"),
|
name = Name.identifier("args"),
|
||||||
index = 0,
|
index = 0,
|
||||||
type = context.irBuiltIns.arrayClass.typeWith(),
|
type = context.irBuiltIns.arrayClass.typeWith(context.irBuiltIns.anyNType),
|
||||||
varargElementType = context.irBuiltIns.anyClass.typeWith(),
|
varargElementType = context.irBuiltIns.anyNType,
|
||||||
isCrossinline = false,
|
isCrossinline = false,
|
||||||
isNoinline = false
|
isNoinline = false
|
||||||
).apply {
|
).apply {
|
||||||
|
|||||||
+7
-15
@@ -7,8 +7,11 @@ package org.jetbrains.kotlin.ir.symbols
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
|
||||||
|
import org.jetbrains.kotlin.ir.util.isLocalClass
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
@@ -31,7 +34,7 @@ object FqNameEqualityChecker : IrClassifierEqualityChecker {
|
|||||||
override fun getHashCode(symbol: IrClassifierSymbol): Int {
|
override fun getHashCode(symbol: IrClassifierSymbol): Int {
|
||||||
if (symbol.isBound) {
|
if (symbol.isBound) {
|
||||||
val owner = symbol.owner
|
val owner = symbol.owner
|
||||||
if (owner is IrClass && !isLocalClass(owner)) {
|
if (owner is IrClass && !owner.isLocalClass()) {
|
||||||
return owner.fqName.hashCode()
|
return owner.fqName.hashCode()
|
||||||
}
|
}
|
||||||
return owner.hashCode()
|
return owner.hashCode()
|
||||||
@@ -54,20 +57,9 @@ object FqNameEqualityChecker : IrClassifierEqualityChecker {
|
|||||||
return parentFqName?.child(name)
|
return parentFqName?.child(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isLocalClass(declaration: IrClass): Boolean {
|
|
||||||
var current: IrDeclarationParent? = declaration
|
|
||||||
while (current != null && current !is IrPackageFragment) {
|
|
||||||
if (current is IrDeclarationWithVisibility && current.visibility == Visibilities.LOCAL)
|
|
||||||
return true
|
|
||||||
current = (current as? IrDeclaration)?.parent
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkViaDeclarations(c1: IrSymbolOwner, c2: IrSymbolOwner): Boolean {
|
private fun checkViaDeclarations(c1: IrSymbolOwner, c2: IrSymbolOwner): Boolean {
|
||||||
if (c1 is IrClass && c2 is IrClass) {
|
if (c1 is IrClass && c2 is IrClass) {
|
||||||
if (isLocalClass(c1) || isLocalClass(c2))
|
if (c1.isLocalClass() || c2.isLocalClass())
|
||||||
return c1 === c2 // Local declarations should be identical
|
return c1 === c2 // Local declarations should be identical
|
||||||
|
|
||||||
return c1.fqName == c2.fqName
|
return c1.fqName == c2.fqName
|
||||||
|
|||||||
@@ -6,22 +6,30 @@
|
|||||||
package org.jetbrains.kotlin.ir.types
|
package org.jetbrains.kotlin.ir.types
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||||
import org.jetbrains.kotlin.ir.symbols.FqNameEqualityChecker
|
import org.jetbrains.kotlin.ir.symbols.FqNameEqualityChecker
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.impl.*
|
import org.jetbrains.kotlin.ir.types.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.checker.convertVariance
|
import org.jetbrains.kotlin.types.checker.convertVariance
|
||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
import org.jetbrains.kotlin.ir.types.isPrimitiveType as irTypePredicates_isPrimitiveType
|
import org.jetbrains.kotlin.ir.types.isPrimitiveType as irTypePredicates_isPrimitiveType
|
||||||
|
|
||||||
interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesContext {
|
interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesContext, TypeSystemCommonBackendContext {
|
||||||
|
|
||||||
val irBuiltIns: IrBuiltIns
|
val irBuiltIns: IrBuiltIns
|
||||||
|
|
||||||
@@ -247,6 +255,67 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
|
|||||||
|
|
||||||
override fun createErrorTypeWithCustomConstructor(debugName: String, constructor: TypeConstructorMarker): KotlinTypeMarker =
|
override fun createErrorTypeWithCustomConstructor(debugName: String, constructor: TypeConstructorMarker): KotlinTypeMarker =
|
||||||
TODO("IrTypeSystemContext doesn't support constraint system resolution")
|
TODO("IrTypeSystemContext doesn't support constraint system resolution")
|
||||||
|
|
||||||
|
override fun TypeConstructorMarker.isFinalClassOrEnumEntryOrAnnotationClassConstructor(): Boolean {
|
||||||
|
val symbol = this as IrClassifierSymbol
|
||||||
|
return symbol is IrClassSymbol && symbol.owner.let {
|
||||||
|
it.modality == Modality.FINAL && !it.isEnumClass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.hasAnnotation(fqName: FqName): Boolean =
|
||||||
|
// TODO: don't fall back to KotlinType to check annotations. Currently testIdentityEquals fails on JVM without it
|
||||||
|
(this as IrAnnotationContainer).hasAnnotation(fqName) ||
|
||||||
|
(this as IrType).toKotlinType().annotations.hasAnnotation(fqName)
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.getAnnotationFirstArgumentValue(fqName: FqName): Any? =
|
||||||
|
(this as? IrType)?.annotations?.firstOrNull { annotation ->
|
||||||
|
annotation.symbol.owner.parentAsClass.descriptor.fqNameSafe == fqName
|
||||||
|
}?.run {
|
||||||
|
if (valueArgumentsCount > 0) (getValueArgument(0) as? IrConst<*>)?.value else null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun TypeConstructorMarker.getTypeParameterClassifier(): TypeParameterMarker? =
|
||||||
|
this as? IrTypeParameterSymbol
|
||||||
|
|
||||||
|
override fun TypeConstructorMarker.isInlineClass(): Boolean =
|
||||||
|
(this as? IrClassSymbol)?.owner?.isInline == true
|
||||||
|
|
||||||
|
override fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker =
|
||||||
|
(this as IrTypeParameterSymbol).owner.superTypes.firstOrNull {
|
||||||
|
val irClass = it.classOrNull?.owner ?: return@firstOrNull false
|
||||||
|
irClass.kind != ClassKind.INTERFACE && irClass.kind != ClassKind.ANNOTATION_CLASS
|
||||||
|
} ?: owner.superTypes.first()
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? {
|
||||||
|
// Code in inlineClassesUtils.kt loads the property with the same name and takes its type. This should have the same effect.
|
||||||
|
val irClass = (this as? IrType)?.classOrNull?.owner ?: return null
|
||||||
|
return irClass.primaryConstructor?.valueParameters?.singleOrNull()?.type
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun TypeConstructorMarker.getPrimitiveType(): PrimitiveType? {
|
||||||
|
// TODO: get rid of descriptor
|
||||||
|
return KotlinBuiltIns.getPrimitiveType((this as IrClassifierSymbol).descriptor as ClassDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun TypeConstructorMarker.getPrimitiveArrayType(): PrimitiveType? {
|
||||||
|
// TODO: get rid of descriptor
|
||||||
|
return KotlinBuiltIns.getPrimitiveArrayType((this as IrClassifierSymbol).descriptor as ClassDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun TypeConstructorMarker.isUnderKotlinPackage(): Boolean {
|
||||||
|
var declaration: IrDeclaration = (this as? IrClassifierSymbol)?.owner as? IrClass ?: return false
|
||||||
|
while (true) {
|
||||||
|
val parent = declaration.parent
|
||||||
|
if (parent is IrPackageFragment) {
|
||||||
|
return parent.fqName.startsWith(KotlinBuiltIns.BUILT_INS_PACKAGE_NAME)
|
||||||
|
}
|
||||||
|
declaration = parent as? IrDeclaration ?: return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun TypeConstructorMarker.getClassFqNameUnsafe(): FqNameUnsafe? =
|
||||||
|
(this as IrClassSymbol).owner.fqNameWhenAvailable?.toUnsafe()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun extractTypeParameters(klass: IrDeclarationParent): List<IrTypeParameter> {
|
fun extractTypeParameters(klass: IrDeclarationParent): List<IrTypeParameter> {
|
||||||
|
|||||||
@@ -304,6 +304,17 @@ val IrDeclarationWithName.fqNameWhenAvailable: FqName?
|
|||||||
|
|
||||||
val IrDeclaration.parentAsClass get() = parent as IrClass
|
val IrDeclaration.parentAsClass get() = parent as IrClass
|
||||||
|
|
||||||
|
fun IrClass.isLocalClass(): Boolean {
|
||||||
|
var current: IrDeclarationParent? = this
|
||||||
|
while (current != null && current !is IrPackageFragment) {
|
||||||
|
if (current is IrDeclarationWithVisibility && current.visibility == Visibilities.LOCAL)
|
||||||
|
return true
|
||||||
|
current = (current as? IrDeclaration)?.parent
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
tailrec fun IrElement.getPackageFragment(): IrPackageFragment? {
|
tailrec fun IrElement.getPackageFragment(): IrPackageFragment? {
|
||||||
if (this is IrPackageFragment) return this
|
if (this is IrPackageFragment) return this
|
||||||
val vParent = (this as? IrDeclaration)?.parent
|
val vParent = (this as? IrDeclaration)?.parent
|
||||||
|
|||||||
Reference in New Issue
Block a user