Add KType.arguments and support 'typeOf' intrinsic
#KT-29917 Fixed #KT-28625 Fixed Also perform minor refactoring.
This commit is contained in:
committed by
SvyatoslavScherbina
parent
f704fd44af
commit
e0d6a4c70e
+1
@@ -41,6 +41,7 @@ class KonanReflectionTypes(module: ModuleDescriptor, internalPackage: FqName) {
|
|||||||
val kMutableProperty0: ClassDescriptor by ClassLookup(kotlinReflectScope)
|
val kMutableProperty0: ClassDescriptor by ClassLookup(kotlinReflectScope)
|
||||||
val kMutableProperty1: ClassDescriptor by ClassLookup(kotlinReflectScope)
|
val kMutableProperty1: ClassDescriptor by ClassLookup(kotlinReflectScope)
|
||||||
val kMutableProperty2: ClassDescriptor by ClassLookup(kotlinReflectScope)
|
val kMutableProperty2: ClassDescriptor by ClassLookup(kotlinReflectScope)
|
||||||
|
val kTypeProjection: ClassDescriptor by ClassLookup(kotlinReflectScope)
|
||||||
|
|
||||||
val kFunctionImpl: ClassDescriptor by ClassLookup(internalScope)
|
val kFunctionImpl: ClassDescriptor by ClassLookup(internalScope)
|
||||||
val kProperty0Impl: ClassDescriptor by ClassLookup(internalScope)
|
val kProperty0Impl: ClassDescriptor by ClassLookup(internalScope)
|
||||||
|
|||||||
+42
-3
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.config.languageVersionSettings
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
@@ -30,8 +29,10 @@ import org.jetbrains.kotlin.ir.util.*
|
|||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
// This is what Context collects about IR.
|
// This is what Context collects about IR.
|
||||||
@@ -249,8 +250,11 @@ internal class KonanSymbols(context: Context, private val symbolTable: SymbolTab
|
|||||||
{ findArrayExtension(it.descriptor, "contentHashCode") }
|
{ findArrayExtension(it.descriptor, "contentHashCode") }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val kotlinCollectionsPackageScope: MemberScope
|
||||||
|
get() = builtInsPackage("kotlin", "collections")
|
||||||
|
|
||||||
private fun findArrayExtension(descriptor: ClassDescriptor, name: String): IrSimpleFunctionSymbol {
|
private fun findArrayExtension(descriptor: ClassDescriptor, name: String): IrSimpleFunctionSymbol {
|
||||||
val functionDescriptor = builtInsPackage("kotlin", "collections")
|
val functionDescriptor = kotlinCollectionsPackageScope
|
||||||
.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND)
|
.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND)
|
||||||
.singleOrNull {
|
.singleOrNull {
|
||||||
it.valueParameters.isEmpty()
|
it.valueParameters.isEmpty()
|
||||||
@@ -403,6 +407,41 @@ internal class KonanSymbols(context: Context, private val symbolTable: SymbolTab
|
|||||||
val kTypeImpl = internalClass("KTypeImpl")
|
val kTypeImpl = internalClass("KTypeImpl")
|
||||||
val kTypeImplForGenerics = internalClass("KTypeImplForGenerics")
|
val kTypeImplForGenerics = internalClass("KTypeImplForGenerics")
|
||||||
|
|
||||||
|
val kTypeProjection = symbolTable.referenceClass(context.reflectionTypes.kTypeProjection)
|
||||||
|
|
||||||
|
private val kTypeProjectionCompanionDescriptor = context.reflectionTypes.kTypeProjection.companionObjectDescriptor!!
|
||||||
|
|
||||||
|
val kTypeProjectionCompanion = symbolTable.referenceClass(kTypeProjectionCompanionDescriptor)
|
||||||
|
|
||||||
|
val kTypeProjectionStar = symbolTable.referenceProperty(
|
||||||
|
kTypeProjectionCompanionDescriptor.unsubstitutedMemberScope
|
||||||
|
.getContributedVariables(Name.identifier("STAR"), NoLookupLocation.FROM_BACKEND).single()
|
||||||
|
)
|
||||||
|
|
||||||
|
val kTypeProjectionFactories: Map<Variance, IrSimpleFunctionSymbol> = Variance.values().toList().associateWith {
|
||||||
|
val factoryName = when (it) {
|
||||||
|
Variance.INVARIANT -> "invariant"
|
||||||
|
Variance.IN_VARIANCE -> "contravariant"
|
||||||
|
Variance.OUT_VARIANCE -> "covariant"
|
||||||
|
}
|
||||||
|
|
||||||
|
symbolTable.referenceSimpleFunction(
|
||||||
|
kTypeProjectionCompanionDescriptor.unsubstitutedMemberScope
|
||||||
|
.getContributedFunctions(Name.identifier(factoryName), NoLookupLocation.FROM_BACKEND).single()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val emptyList = symbolTable.referenceSimpleFunction(
|
||||||
|
kotlinCollectionsPackageScope
|
||||||
|
.getContributedFunctions(Name.identifier("emptyList"), NoLookupLocation.FROM_BACKEND)
|
||||||
|
.single { it.valueParameters.isEmpty() }
|
||||||
|
)
|
||||||
|
|
||||||
|
val listOf = symbolTable.referenceSimpleFunction(
|
||||||
|
kotlinCollectionsPackageScope
|
||||||
|
.getContributedFunctions(Name.identifier("listOf"), NoLookupLocation.FROM_BACKEND)
|
||||||
|
.single { it.valueParameters.size == 1 && it.valueParameters[0].isVararg }
|
||||||
|
)
|
||||||
val listOfInternal = internalFunction("listOfInternal")
|
val listOfInternal = internalFunction("listOfInternal")
|
||||||
|
|
||||||
val threadLocal =
|
val threadLocal =
|
||||||
|
|||||||
+3
-1
@@ -40,6 +40,8 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
|
|
||||||
private object DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL : IrDeclarationOriginImpl("FUNCTION_REFERENCE_IMPL")
|
private object DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL : IrDeclarationOriginImpl("FUNCTION_REFERENCE_IMPL")
|
||||||
|
|
||||||
|
private val kTypeGenerator = KTypeGenerator(context)
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
var generatedClasses = mutableListOf<IrClass>()
|
var generatedClasses = mutableListOf<IrClass>()
|
||||||
irFile.transform(object: IrElementTransformerVoidWithContext() {
|
irFile.transform(object: IrElementTransformerVoidWithContext() {
|
||||||
@@ -266,7 +268,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
val needReceiver = boundFunctionParameters.singleOrNull()?.descriptor is ReceiverParameterDescriptor
|
val needReceiver = boundFunctionParameters.singleOrNull()?.descriptor is ReceiverParameterDescriptor
|
||||||
val receiver = if (needReceiver) irGet(valueParameters.single()) else irNull()
|
val receiver = if (needReceiver) irGet(valueParameters.single()) else irNull()
|
||||||
putValueArgument(3, receiver)
|
putValueArgument(3, receiver)
|
||||||
putValueArgument(4, irKType(this@CallableReferenceLowering.context, referencedFunction.returnType))
|
putValueArgument(4, with(kTypeGenerator) { irKType(referencedFunction.returnType) })
|
||||||
}
|
}
|
||||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol, irBuiltIns.unitType)
|
+IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol, irBuiltIns.unitType)
|
||||||
// Save all arguments to fields.
|
// Save all arguments to fields.
|
||||||
|
|||||||
+4
-2
@@ -34,6 +34,8 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
internal class PropertyDelegationLowering(val context: Context) : FileLoweringPass {
|
internal class PropertyDelegationLowering(val context: Context) : FileLoweringPass {
|
||||||
private var tempIndex = 0
|
private var tempIndex = 0
|
||||||
|
|
||||||
|
private val kTypeGenerator = KTypeGenerator(context)
|
||||||
|
|
||||||
private fun getKPropertyImplConstructor(receiverTypes: List<IrType>,
|
private fun getKPropertyImplConstructor(receiverTypes: List<IrType>,
|
||||||
returnType: IrType,
|
returnType: IrType,
|
||||||
isLocal: Boolean,
|
isLocal: Boolean,
|
||||||
@@ -253,7 +255,7 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
|
|||||||
isMutable = setterCallableReference != null)
|
isMutable = setterCallableReference != null)
|
||||||
val initializer = irCall(symbol.owner, constructorTypeArguments).apply {
|
val initializer = irCall(symbol.owner, constructorTypeArguments).apply {
|
||||||
putValueArgument(0, irString(propertyDescriptor.name.asString()))
|
putValueArgument(0, irString(propertyDescriptor.name.asString()))
|
||||||
putValueArgument(1, irKType(this@PropertyDelegationLowering.context, returnType))
|
putValueArgument(1, with(kTypeGenerator) { irKType(returnType) })
|
||||||
if (getterCallableReference != null)
|
if (getterCallableReference != null)
|
||||||
putValueArgument(2, getterCallableReference)
|
putValueArgument(2, getterCallableReference)
|
||||||
if (setterCallableReference != null)
|
if (setterCallableReference != null)
|
||||||
@@ -274,7 +276,7 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
|
|||||||
isMutable = false)
|
isMutable = false)
|
||||||
val initializer = irCall(symbol.owner, constructorTypeArguments).apply {
|
val initializer = irCall(symbol.owner, constructorTypeArguments).apply {
|
||||||
putValueArgument(0, irString(propertyDescriptor.name.asString()))
|
putValueArgument(0, irString(propertyDescriptor.name.asString()))
|
||||||
putValueArgument(1, irKType(this@PropertyDelegationLowering.context, propertyType))
|
putValueArgument(1, with(kTypeGenerator) { irKType(propertyType) })
|
||||||
}
|
}
|
||||||
return initializer
|
return initializer
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -47,6 +47,8 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
|||||||
return expression
|
return expression
|
||||||
if (Symbols.isLateinitIsInitializedPropertyGetter(callee.symbol))
|
if (Symbols.isLateinitIsInitializedPropertyGetter(callee.symbol))
|
||||||
return expression
|
return expression
|
||||||
|
if (callee.isTypeOfIntrinsic())
|
||||||
|
return expression
|
||||||
|
|
||||||
val actualCallee = getFunctionDeclaration(callee.symbol)
|
val actualCallee = getFunctionDeclaration(callee.symbol)
|
||||||
|
|
||||||
|
|||||||
+28
-5
@@ -9,12 +9,16 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
|||||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
|
import org.jetbrains.kotlin.backend.konan.error
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.typeWithoutArguments
|
import org.jetbrains.kotlin.backend.konan.ir.typeWithoutArguments
|
||||||
import org.jetbrains.kotlin.backend.konan.reportCompilationError
|
import org.jetbrains.kotlin.backend.konan.reportCompilationError
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.irCall
|
import org.jetbrains.kotlin.ir.util.irCall
|
||||||
|
import org.jetbrains.kotlin.ir.util.isTypeOfIntrinsic
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,23 +30,32 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
|
|||||||
|
|
||||||
private val symbols get() = context.ir.symbols
|
private val symbols get() = context.ir.symbols
|
||||||
|
|
||||||
|
private val kTypeGenerator = KTypeGenerator(
|
||||||
|
context,
|
||||||
|
eraseTypeParameters = true // Mimic JVM BE behaviour until proper type parameter impl is ready.
|
||||||
|
)
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
||||||
|
|
||||||
override fun visitClassReference(expression: IrClassReference): IrExpression {
|
override fun visitClassReference(expression: IrClassReference): IrExpression {
|
||||||
expression.transformChildrenVoid()
|
expression.transformChildrenVoid()
|
||||||
|
|
||||||
val builder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol,
|
val builder = createIrBuilder(expression)
|
||||||
expression.startOffset, expression.endOffset)
|
|
||||||
|
|
||||||
return builder.irKClass(context, expression.symbol)
|
val symbol = expression.symbol
|
||||||
|
return if (symbol is IrClassSymbol) {
|
||||||
|
builder.irKClass(context, symbol)
|
||||||
|
} else {
|
||||||
|
// E.g. for `T::class` in a body of an inline function itself.
|
||||||
|
builder.irCall(context.ir.symbols.ThrowNullPointerException.owner)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitGetClass(expression: IrGetClass): IrExpression {
|
override fun visitGetClass(expression: IrGetClass): IrExpression {
|
||||||
expression.transformChildrenVoid()
|
expression.transformChildrenVoid()
|
||||||
|
|
||||||
val builder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol,
|
val builder = createIrBuilder(expression)
|
||||||
expression.startOffset, expression.endOffset)
|
|
||||||
|
|
||||||
val typeArgument = expression.argument.type
|
val typeArgument = expression.argument.type
|
||||||
|
|
||||||
@@ -91,10 +104,20 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
|
|||||||
expression.startOffset, expression.endOffset,
|
expression.startOffset, expression.endOffset,
|
||||||
context.ir.symbols.immutableBlob.typeWithoutArguments,
|
context.ir.symbols.immutableBlob.typeWithoutArguments,
|
||||||
IrConstKind.String, builder.toString()))
|
IrConstKind.String, builder.toString()))
|
||||||
|
} else if (expression.symbol.owner.isTypeOfIntrinsic()) {
|
||||||
|
val type = expression.getTypeArgument(0)
|
||||||
|
?: error(irFile, expression, "missing type argument")
|
||||||
|
return with (kTypeGenerator) { createIrBuilder(expression).irKType(type) }
|
||||||
}
|
}
|
||||||
|
|
||||||
return expression
|
return expression
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createIrBuilder(element: IrElement) = context.createIrBuilder(
|
||||||
|
currentScope!!.scope.scopeOwnerSymbol,
|
||||||
|
element.startOffset,
|
||||||
|
element.endOffset
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+79
-27
@@ -8,50 +8,102 @@ package org.jetbrains.kotlin.backend.konan.lower
|
|||||||
import org.jetbrains.kotlin.backend.konan.InteropFqNames
|
import org.jetbrains.kotlin.backend.konan.InteropFqNames
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.typeWithStarProjections
|
import org.jetbrains.kotlin.backend.konan.ir.typeWithStarProjections
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.typeWithoutArguments
|
||||||
import org.jetbrains.kotlin.backend.konan.isObjCClass
|
import org.jetbrains.kotlin.backend.konan.isObjCClass
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.builders.irBoolean
|
|
||||||
import org.jetbrains.kotlin.ir.builders.irCall
|
|
||||||
import org.jetbrains.kotlin.ir.builders.irString
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||||
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.types.*
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
|
||||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
|
||||||
import org.jetbrains.kotlin.ir.types.isMarkedNullable
|
|
||||||
import org.jetbrains.kotlin.ir.util.constructors
|
import org.jetbrains.kotlin.ir.util.constructors
|
||||||
import org.jetbrains.kotlin.ir.util.irCall
|
import org.jetbrains.kotlin.ir.util.irCall
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
|
||||||
|
|
||||||
internal fun IrBuilderWithScope.irKType(context: KonanBackendContext, type: IrType): IrExpression {
|
internal class KTypeGenerator(
|
||||||
val kTypeImplSymbol = context.ir.symbols.kTypeImpl
|
private val context: KonanBackendContext,
|
||||||
val kTypeImplForGenericsSymbol = context.ir.symbols.kTypeImplForGenerics
|
private val eraseTypeParameters: Boolean = false
|
||||||
|
) {
|
||||||
|
private val symbols = context.ir.symbols
|
||||||
|
|
||||||
val kTypeImplConstructorSymbol = kTypeImplSymbol.constructors.single()
|
fun IrBuilderWithScope.irKType(type: IrType): IrExpression = if (type !is IrSimpleType) {
|
||||||
val kTypeImplForGenericsConstructorSymbol = kTypeImplForGenericsSymbol.constructors.single()
|
// Represent as non-denotable type:
|
||||||
|
irKTypeImpl(
|
||||||
val classifierOrNull = type.classifierOrNull
|
kClassifier = irNull(),
|
||||||
|
irTypeArguments = emptyList(),
|
||||||
return if (classifierOrNull !is IrClassSymbol) {
|
isMarkedNullable = false
|
||||||
// IrTypeParameterSymbol
|
)
|
||||||
irCall(kTypeImplForGenericsConstructorSymbol)
|
|
||||||
} else {
|
} else {
|
||||||
val returnKClass = irKClass(context, classifierOrNull)
|
val classifier = type.classifier
|
||||||
irCall(kTypeImplConstructorSymbol).apply {
|
|
||||||
putValueArgument(0, returnKClass)
|
if (classifier is IrClassSymbol) {
|
||||||
putValueArgument(1, irBoolean(type.isMarkedNullable()))
|
irKTypeImpl(
|
||||||
|
kClassifier = irKClass(classifier),
|
||||||
|
irTypeArguments = type.arguments,
|
||||||
|
isMarkedNullable = type.hasQuestionMark
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
if (eraseTypeParameters) {
|
||||||
|
irKType(context.irBuiltIns.anyNType)
|
||||||
|
} else {
|
||||||
|
irCall(symbols.kTypeImplForGenerics.constructors.single())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrBuilderWithScope.irKTypeImpl(
|
||||||
|
kClassifier: IrExpression,
|
||||||
|
irTypeArguments: List<IrTypeArgument>,
|
||||||
|
isMarkedNullable: Boolean
|
||||||
|
): IrExpression = irCall(symbols.kTypeImpl.constructors.single()).apply {
|
||||||
|
putValueArgument(0, kClassifier)
|
||||||
|
putValueArgument(1, irKTypeProjectionsList(irTypeArguments))
|
||||||
|
putValueArgument(2, irBoolean(isMarkedNullable))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrBuilderWithScope.irKClass(symbol: IrClassSymbol) = irKClass(this@KTypeGenerator.context, symbol)
|
||||||
|
|
||||||
|
private fun IrBuilderWithScope.irKTypeProjectionsList(
|
||||||
|
irTypeArguments: List<IrTypeArgument>
|
||||||
|
): IrMemberAccessExpression {
|
||||||
|
val kTypeProjectionType = symbols.kTypeProjection.typeWithoutArguments
|
||||||
|
|
||||||
|
return if (irTypeArguments.isEmpty()) {
|
||||||
|
irCall(symbols.emptyList, listOf(kTypeProjectionType))
|
||||||
|
} else {
|
||||||
|
irCall(symbols.listOf, listOf(kTypeProjectionType)).apply {
|
||||||
|
putValueArgument(0, IrVarargImpl(
|
||||||
|
startOffset,
|
||||||
|
endOffset,
|
||||||
|
type = symbols.array.typeWith(kTypeProjectionType),
|
||||||
|
varargElementType = kTypeProjectionType,
|
||||||
|
elements = irTypeArguments.map { irKTypeProjection(it) }
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrBuilderWithScope.irKTypeProjection(argument: IrTypeArgument): IrExpression {
|
||||||
|
return when (argument) {
|
||||||
|
is IrTypeProjection -> irCall(symbols.kTypeProjectionFactories.getValue(argument.variance)).apply {
|
||||||
|
dispatchReceiver = irGetObject(symbols.kTypeProjectionCompanion)
|
||||||
|
putValueArgument(0, irKType(argument.type))
|
||||||
|
}
|
||||||
|
|
||||||
|
is IrStarProjection -> irCall(symbols.kTypeProjectionStar.owner.getter!!).apply {
|
||||||
|
dispatchReceiver = irGetObject(symbols.kTypeProjectionCompanion)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> error("Unexpected IrTypeArgument: $argument (${argument::class})")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun IrBuilderWithScope.irKClass(context: KonanBackendContext, symbol: IrClassifierSymbol): IrExpression {
|
internal fun IrBuilderWithScope.irKClass(context: KonanBackendContext, symbol: IrClassSymbol): IrExpression {
|
||||||
val symbols = context.ir.symbols
|
val symbols = context.ir.symbols
|
||||||
return when {
|
return when {
|
||||||
symbol !is IrClassSymbol -> // E.g. for `T::class` in a body of an inline function itself.
|
|
||||||
irCall(symbols.ThrowNullPointerException.owner)
|
|
||||||
|
|
||||||
symbol.descriptor.isObjCClass() ->
|
symbol.descriptor.isObjCClass() ->
|
||||||
irKClassUnsupported(context, "KClass for Objective-C classes is not supported yet")
|
irKClassUnsupported(context, "KClass for Objective-C classes is not supported yet")
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.backend.konan.KonanCompilationException
|
|||||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.allParameters
|
import org.jetbrains.kotlin.backend.konan.ir.allParameters
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.containsNull
|
import org.jetbrains.kotlin.backend.konan.ir.containsNull
|
||||||
|
import org.jetbrains.kotlin.builtins.KOTLIN_REFLECT_FQ_NAME
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
@@ -434,3 +435,8 @@ fun IrClass.defaultOrNullableType(hasQuestionMark: Boolean) =
|
|||||||
|
|
||||||
fun IrFunction.isRestrictedSuspendFunction(languageVersionSettings: LanguageVersionSettings): Boolean =
|
fun IrFunction.isRestrictedSuspendFunction(languageVersionSettings: LanguageVersionSettings): Boolean =
|
||||||
this.descriptor.extensionReceiverParameter?.type?.isRestrictsSuspensionReceiver(languageVersionSettings) == true
|
this.descriptor.extensionReceiverParameter?.type?.isRestrictsSuspensionReceiver(languageVersionSettings) == true
|
||||||
|
|
||||||
|
fun IrFunction.isTypeOfIntrinsic(): Boolean =
|
||||||
|
this.name.asString() == "typeOf" &&
|
||||||
|
this.valueParameters.isEmpty() &&
|
||||||
|
(this.parent as? IrPackageFragment)?.fqName == KOTLIN_REFLECT_FQ_NAME
|
||||||
|
|||||||
@@ -5,15 +5,21 @@
|
|||||||
|
|
||||||
package kotlin.native.internal
|
package kotlin.native.internal
|
||||||
|
|
||||||
import kotlin.reflect.KClassifier
|
import kotlin.reflect.*
|
||||||
import kotlin.reflect.KType
|
|
||||||
|
|
||||||
internal class KTypeImpl(override val classifier: KClassifier?, override val isMarkedNullable: Boolean) : KType {
|
internal class KTypeImpl(
|
||||||
|
override val classifier: KClassifier?,
|
||||||
|
override val arguments: List<KTypeProjection>,
|
||||||
|
override val isMarkedNullable: Boolean
|
||||||
|
) : KType {
|
||||||
override fun equals(other: Any?) =
|
override fun equals(other: Any?) =
|
||||||
other is KTypeImpl && classifier == other.classifier && isMarkedNullable == other.isMarkedNullable
|
other is KTypeImpl &&
|
||||||
|
this.classifier == other.classifier &&
|
||||||
|
this.arguments == other.arguments &&
|
||||||
|
this.isMarkedNullable == other.isMarkedNullable
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
return (classifier?.hashCode() ?: 0) * 31 + if (isMarkedNullable) 1 else 0
|
return (classifier?.hashCode() ?: 0) * 31 * 31 + this.arguments.hashCode() * 31 + if (isMarkedNullable) 1 else 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,6 +27,8 @@ internal class KTypeImplForGenerics : KType {
|
|||||||
override val classifier: KClassifier?
|
override val classifier: KClassifier?
|
||||||
get() = error("Generic types are not yet supported in reflection")
|
get() = error("Generic types are not yet supported in reflection")
|
||||||
|
|
||||||
|
override val arguments: List<KTypeProjection> get() = emptyList()
|
||||||
|
|
||||||
override val isMarkedNullable: Boolean
|
override val isMarkedNullable: Boolean
|
||||||
get() = error("Generic types are not yet supported in reflection")
|
get() = error("Generic types are not yet supported in reflection")
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,17 @@ public interface KType {
|
|||||||
@SinceKotlin("1.1")
|
@SinceKotlin("1.1")
|
||||||
public val classifier: KClassifier?
|
public val classifier: KClassifier?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type arguments passed for the parameters of the classifier in this type.
|
||||||
|
* For example, in the type `Array<out Number>` the only type argument is `out Number`.
|
||||||
|
*
|
||||||
|
* In case this type is based on an inner class, the returned list contains the type arguments provided for the innermost class first,
|
||||||
|
* then its outer class, and so on.
|
||||||
|
* For example, in the type `Outer<A, B>.Inner<C, D>` the returned list is `[C, D, A, B]`.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
public val arguments: List<KTypeProjection>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `true` if this type was marked nullable in the source code.
|
* `true` if this type was marked nullable in the source code.
|
||||||
*
|
*
|
||||||
@@ -38,3 +49,56 @@ public interface KType {
|
|||||||
*/
|
*/
|
||||||
public val isMarkedNullable: Boolean
|
public val isMarkedNullable: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a type projection. Type projection is usually the argument to another type in a type usage.
|
||||||
|
* For example, in the type `Array<out Number>`, `out Number` is the covariant projection of the type represented by the class `Number`.
|
||||||
|
*
|
||||||
|
* Type projection is either the star projection, or an entity consisting of a specific type plus optional variance.
|
||||||
|
*
|
||||||
|
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/generics.html#type-projections)
|
||||||
|
* for more information.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
public data class KTypeProjection constructor(
|
||||||
|
/**
|
||||||
|
* The use-site variance specified in the projection, or `null` if this is a star projection.
|
||||||
|
*/
|
||||||
|
public val variance: KVariance?,
|
||||||
|
/**
|
||||||
|
* The type specified in the projection, or `null` if this is a star projection.
|
||||||
|
*/
|
||||||
|
public val type: KType?
|
||||||
|
) {
|
||||||
|
public companion object {
|
||||||
|
/**
|
||||||
|
* Star projection, denoted by the `*` character.
|
||||||
|
* For example, in the type `KClass<*>`, `*` is the star projection.
|
||||||
|
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/generics.html#star-projections)
|
||||||
|
* for more information.
|
||||||
|
*/
|
||||||
|
public val STAR: KTypeProjection = KTypeProjection(null, null)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an invariant projection of a given type. Invariant projection is just the type itself,
|
||||||
|
* without any use-site variance modifiers applied to it.
|
||||||
|
* For example, in the type `Set<String>`, `String` is an invariant projection of the type represented by the class `String`.
|
||||||
|
*/
|
||||||
|
public fun invariant(type: KType): KTypeProjection =
|
||||||
|
KTypeProjection(KVariance.INVARIANT, type)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a contravariant projection of a given type, denoted by the `in` modifier applied to a type.
|
||||||
|
* For example, in the type `MutableList<in Number>`, `in Number` is a contravariant projection of the type of class `Number`.
|
||||||
|
*/
|
||||||
|
public fun contravariant(type: KType): KTypeProjection =
|
||||||
|
KTypeProjection(KVariance.IN, type)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a covariant projection of a given type, denoted by the `out` modifier applied to a type.
|
||||||
|
* For example, in the type `Array<out Number>`, `out Number` is a covariant projection of the type of class `Number`.
|
||||||
|
*/
|
||||||
|
public fun covariant(type: KType): KTypeProjection =
|
||||||
|
KTypeProjection(KVariance.OUT, type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kotlin.reflect
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents variance applied to a type parameter on the declaration site (*declaration-site variance*),
|
||||||
|
* or to a type in a projection (*use-site variance*).
|
||||||
|
*
|
||||||
|
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/generics.html#variance)
|
||||||
|
* for more information.
|
||||||
|
*
|
||||||
|
* @see [KTypeParameter.variance]
|
||||||
|
* @see [KTypeProjection]
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
enum class KVariance {
|
||||||
|
/**
|
||||||
|
* The affected type parameter or type is *invariant*, which means it has no variance applied to it.
|
||||||
|
*/
|
||||||
|
INVARIANT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The affected type parameter or type is *contravariant*. Denoted by the `in` modifier in the source code.
|
||||||
|
*/
|
||||||
|
IN,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The affected type parameter or type is *covariant*. Denoted by the `out` modifier in the source code.
|
||||||
|
*/
|
||||||
|
OUT,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user