JVM IR: do not use KotlinTypeMapper in IrTypeMapper.mapType

This commit is contained in:
Alexander Udalov
2019-05-14 18:36:15 +02:00
parent 1e16c0a447
commit a15575d546
8 changed files with 368 additions and 39 deletions
@@ -1433,7 +1433,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
private fun hasNothingInNonContravariantPosition(kotlinType: KotlinType): Boolean =
SimpleClassicTypeSystemContext.hasNothingInNonContravariantPosition(kotlinType)
private fun TypeSystemContext.hasNothingInNonContravariantPosition(type: KotlinTypeMarker): Boolean {
fun TypeSystemContext.hasNothingInNonContravariantPosition(type: KotlinTypeMarker): Boolean {
val typeConstructor = type.typeConstructor()
for (i in 0 until type.argumentsCount()) {
@@ -6,40 +6,65 @@
package org.jetbrains.kotlin.backend.jvm.codegen
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.ClassBuilderMode
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
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.state.KotlinTypeMapper
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
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.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.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.commons.Method
class IrTypeMapper(private val context: JvmBackendContext) {
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) =
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)
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)
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) =
kotlinTypeMapper.mapToCallableMethod(f.descriptor, superCall, kind, resolvedCall)
@@ -47,13 +72,188 @@ class IrTypeMapper(private val context: JvmBackendContext) {
fun writeFormalTypeParameters(irParameters: List<IrTypeParameter>, sw: JvmSignatureWriter) =
kotlinTypeMapper.writeFormalTypeParameters(irParameters.map { it.descriptor }, sw)
fun boxType(irType: IrType) =
fun boxType(irType: IrType): Type =
AsmUtil.boxType(mapType(irType), irType.toKotlinType(), kotlinTypeMapper)
fun mapType(
type: IrType,
mode: TypeMappingMode = TypeMappingMode.DEFAULT,
sw: JvmSignatureWriter? = null
): Type =
kotlinTypeMapper.mapType(type.toKotlinType(), sw, mode)
): Type {
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
}
@@ -5,14 +5,20 @@
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.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.types.IrSimpleType
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.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.name.SpecialNames
import org.jetbrains.org.objectweb.asm.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 =
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()
}
@@ -5,7 +5,10 @@
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
/**
@@ -19,10 +22,14 @@ object UnsafeCoerce : IntrinsicMethod() {
override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? {
val from = expression.getTypeArgument(0)!!
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 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()
}
}
@@ -84,8 +84,8 @@ private class FunctionNVarargInvokeLowering(var context: JvmBackendContext) : Cl
symbol = IrValueParameterSymbolImpl(varargParameterDescriptor),
name = Name.identifier("args"),
index = 0,
type = context.irBuiltIns.arrayClass.typeWith(),
varargElementType = context.irBuiltIns.anyClass.typeWith(),
type = context.irBuiltIns.arrayClass.typeWith(context.irBuiltIns.anyNType),
varargElementType = context.irBuiltIns.anyNType,
isCrossinline = false,
isNoinline = false
).apply {
@@ -7,8 +7,11 @@ package org.jetbrains.kotlin.ir.symbols
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrClass
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.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
@@ -31,7 +34,7 @@ object FqNameEqualityChecker : IrClassifierEqualityChecker {
override fun getHashCode(symbol: IrClassifierSymbol): Int {
if (symbol.isBound) {
val owner = symbol.owner
if (owner is IrClass && !isLocalClass(owner)) {
if (owner is IrClass && !owner.isLocalClass()) {
return owner.fqName.hashCode()
}
return owner.hashCode()
@@ -54,20 +57,9 @@ object FqNameEqualityChecker : IrClassifierEqualityChecker {
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 {
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.fqName == c2.fqName
@@ -6,22 +6,30 @@
package org.jetbrains.kotlin.ir.types
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.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.declarations.*
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.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
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.checker.convertVariance
import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.ir.types.isPrimitiveType as irTypePredicates_isPrimitiveType
interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesContext {
interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesContext, TypeSystemCommonBackendContext {
val irBuiltIns: IrBuiltIns
@@ -247,6 +255,67 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
override fun createErrorTypeWithCustomConstructor(debugName: String, constructor: TypeConstructorMarker): KotlinTypeMarker =
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> {
@@ -304,6 +304,17 @@ val IrDeclarationWithName.fqNameWhenAvailable: FqName?
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? {
if (this is IrPackageFragment) return this
val vParent = (this as? IrDeclaration)?.parent