[IR] Supported non-reified typeOf

This commit is contained in:
Igor Chevdar
2020-09-20 20:41:04 +05:00
parent 1aef9da517
commit d67067a49e
18 changed files with 396 additions and 147 deletions
@@ -268,13 +268,6 @@ internal val testProcessorPhase = makeKonanFileOpPhase(
description = "Unit test processor" description = "Unit test processor"
) )
internal val enumClassPhase = makeKonanFileOpPhase(
{ context, irFile -> EnumClassLowering(context).run(irFile) },
name = "Enums",
description = "Enum classes lowering",
prerequisite = setOf(enumConstructorsPhase) // TODO: make weak dependency on `testProcessorPhase`
)
internal val delegationPhase = makeKonanFileLoweringPhase( internal val delegationPhase = makeKonanFileLoweringPhase(
::PropertyDelegationLowering, ::PropertyDelegationLowering,
name = "Delegation", name = "Delegation",
@@ -288,6 +281,13 @@ internal val functionReferencePhase = makeKonanFileLoweringPhase(
prerequisite = setOf(delegationPhase, localFunctionsPhase) // TODO: make weak dependency on `testProcessorPhase` prerequisite = setOf(delegationPhase, localFunctionsPhase) // TODO: make weak dependency on `testProcessorPhase`
) )
internal val enumClassPhase = makeKonanFileOpPhase(
{ context, irFile -> EnumClassLowering(context).run(irFile) },
name = "Enums",
description = "Enum classes lowering",
prerequisite = setOf(enumConstructorsPhase, functionReferencePhase) // TODO: make weak dependency on `testProcessorPhase`
)
internal val singleAbstractMethodPhase = makeKonanFileLoweringPhase( internal val singleAbstractMethodPhase = makeKonanFileLoweringPhase(
::NativeSingleAbstractMethodLowering, ::NativeSingleAbstractMethodLowering,
name = "SingleAbstractMethod", name = "SingleAbstractMethod",
@@ -45,6 +45,8 @@ class KonanReflectionTypes(module: ModuleDescriptor, internalPackage: FqName) {
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 kTypeProjection: ClassDescriptor by ClassLookup(kotlinReflectScope)
val kType: ClassDescriptor by ClassLookup(kotlinReflectScope)
val kVariance: ClassDescriptor by ClassLookup(kotlinReflectScope)
val kFunctionImpl: ClassDescriptor by ClassLookup(internalScope) val kFunctionImpl: ClassDescriptor by ClassLookup(internalScope)
val kSuspendFunctionImpl: ClassDescriptor by ClassLookup(internalScope) val kSuspendFunctionImpl: ClassDescriptor by ClassLookup(internalScope)
@@ -56,4 +58,6 @@ class KonanReflectionTypes(module: ModuleDescriptor, internalPackage: FqName) {
val kMutableProperty2Impl: ClassDescriptor by ClassLookup(internalScope) val kMutableProperty2Impl: ClassDescriptor by ClassLookup(internalScope)
val kLocalDelegatedPropertyImpl: ClassDescriptor by ClassLookup(internalScope) val kLocalDelegatedPropertyImpl: ClassDescriptor by ClassLookup(internalScope)
val kLocalDelegatedMutablePropertyImpl: ClassDescriptor by ClassLookup(internalScope) val kLocalDelegatedMutablePropertyImpl: ClassDescriptor by ClassLookup(internalScope)
val typeOf = kotlinReflectScope.getContributedFunctions(Name.identifier("typeOf"), NoLookupLocation.FROM_REFLECTION).single()
} }
@@ -450,14 +450,21 @@ internal class KonanSymbols(
val kLocalDelegatedPropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedPropertyImpl) val kLocalDelegatedPropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedPropertyImpl)
val kLocalDelegatedMutablePropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedMutablePropertyImpl) val kLocalDelegatedMutablePropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedMutablePropertyImpl)
val typeOf = symbolTable.referenceSimpleFunction(context.reflectionTypes.typeOf)
val kType = symbolTable.referenceClass(context.reflectionTypes.kType)
val kVariance = symbolTable.referenceClass(context.reflectionTypes.kVariance)
val getClassTypeInfo = internalFunction("getClassTypeInfo") val getClassTypeInfo = internalFunction("getClassTypeInfo")
val getObjectTypeInfo = internalFunction("getObjectTypeInfo") val getObjectTypeInfo = internalFunction("getObjectTypeInfo")
val kClassImpl = internalClass("KClassImpl") val kClassImpl = internalClass("KClassImpl")
val kClassImplConstructor by lazy { kClassImpl.constructors.single() } val kClassImplConstructor by lazy { kClassImpl.constructors.single() }
val kClassUnsupportedImpl = internalClass("KClassUnsupportedImpl") val kClassUnsupportedImpl = internalClass("KClassUnsupportedImpl")
val kClassUnsupportedImplConstructor by lazy { kClassUnsupportedImpl.constructors.single() } val kClassUnsupportedImplConstructor by lazy { kClassUnsupportedImpl.constructors.single() }
val kTypeParameterImpl = internalClass("KTypeParameterImpl")
val kTypeImpl = internalClass("KTypeImpl") val kTypeImpl = internalClass("KTypeImpl")
val kTypeImplForGenerics = internalClass("KTypeImplForGenerics") val kTypeImplForTypeParametersWithRecursiveBounds = internalClass("KTypeImplForTypeParametersWithRecursiveBounds")
val kTypeProjection = symbolTable.referenceClass(context.reflectionTypes.kTypeProjection) val kTypeProjection = symbolTable.referenceClass(context.reflectionTypes.kTypeProjection)
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.ir.util.isSuspend
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.konan.library.KonanLibrary import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.library.uniqueName import org.jetbrains.kotlin.library.uniqueName
import org.jetbrains.kotlin.name.Name
// This file describes the ABI for Kotlin descriptors of exported declarations. // This file describes the ABI for Kotlin descriptors of exported declarations.
@@ -112,6 +113,7 @@ internal val IrClass.kotlinObjCClassInfoSymbolName: String
} }
val IrFunction.functionName get() = with(KonanBinaryInterface) { functionName } val IrFunction.functionName get() = with(KonanBinaryInterface) { functionName }
val IrFunction.fullName get() = parent.fqNameForIrSerialization.child(Name.identifier(functionName)).asString()
val IrFunction.symbolName get() = with(KonanBinaryInterface) { symbolName } val IrFunction.symbolName get() = with(KonanBinaryInterface) { symbolName }
@@ -33,8 +33,6 @@ 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,
@@ -109,19 +107,20 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
override fun visitPropertyReference(expression: IrPropertyReference): IrExpression { override fun visitPropertyReference(expression: IrPropertyReference): IrExpression {
expression.transformChildrenVoid(this) expression.transformChildrenVoid(this)
val kTypeGenerator = KTypeGenerator(context, irFile, expression)
val startOffset = expression.startOffset val startOffset = expression.startOffset
val endOffset = expression.endOffset val endOffset = expression.endOffset
val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset) val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset)
irBuilder.run { irBuilder.run {
val receiversCount = listOf(expression.dispatchReceiver, expression.extensionReceiver).count { it != null } val receiversCount = listOf(expression.dispatchReceiver, expression.extensionReceiver).count { it != null }
return when (receiversCount) { return when (receiversCount) {
1 -> createKProperty(expression, this) // Has receiver. 1 -> createKProperty(expression, kTypeGenerator, this) // Has receiver.
2 -> error("Callable reference to properties with two receivers is not allowed: ${expression.symbol.owner.name}") 2 -> error("Callable reference to properties with two receivers is not allowed: ${expression.symbol.owner.name}")
else -> { // Cache KProperties with no arguments. else -> { // Cache KProperties with no arguments.
val field = kProperties.getOrPut(expression.symbol.owner) { val field = kProperties.getOrPut(expression.symbol.owner) {
createKProperty(expression, this) to kProperties.size createKProperty(expression, kTypeGenerator, this) to kProperties.size
} }
irCall(arrayItemGetter).apply { irCall(arrayItemGetter).apply {
@@ -149,6 +148,7 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
createLocalKProperty( createLocalKProperty(
expression.symbol.owner.name.asString(), expression.symbol.owner.name.asString(),
expression.getter.owner.returnType, expression.getter.owner.returnType,
KTypeGenerator(this@PropertyDelegationLowering.context, irFile, expression),
this this
) to kProperties.size ) to kProperties.size
} }
@@ -172,7 +172,11 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
} }
} }
private fun createKProperty(expression: IrPropertyReference, irBuilder: IrBuilderWithScope): IrExpression { private fun createKProperty(
expression: IrPropertyReference,
kTypeGenerator: KTypeGenerator,
irBuilder: IrBuilderWithScope
): IrExpression {
val startOffset = expression.startOffset val startOffset = expression.startOffset
val endOffset = expression.endOffset val endOffset = expression.endOffset
return irBuilder.irBlock(expression) { return irBuilder.irBlock(expression) {
@@ -263,6 +267,7 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
private fun createLocalKProperty(propertyName: String, private fun createLocalKProperty(propertyName: String,
propertyType: IrType, propertyType: IrType,
kTypeGenerator: KTypeGenerator,
irBuilder: IrBuilderWithScope): IrExpression { irBuilder: IrBuilderWithScope): IrExpression {
irBuilder.run { irBuilder.run {
val (symbol, constructorTypeArguments) = getKPropertyImplConstructor( val (symbol, constructorTypeArguments) = getKPropertyImplConstructor(
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.backend.common.push
import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.konan.llvm.functionName import org.jetbrains.kotlin.backend.konan.llvm.fullName
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.ReceiverParameterDescriptor import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
@@ -49,8 +49,6 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
declaration.origin == DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL declaration.origin == DECLARATION_ORIGIN_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() {
@@ -151,7 +149,7 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
fun transformFunctionReference(expression: IrFunctionReference, samSuperType: IrType? = null): IrExpression { fun transformFunctionReference(expression: IrFunctionReference, samSuperType: IrType? = null): IrExpression {
val parent: IrDeclarationContainer = (currentClass?.irElement as? IrClass) ?: irFile val parent: IrDeclarationContainer = (currentClass?.irElement as? IrClass) ?: irFile
val loweredFunctionReference = FunctionReferenceBuilder(parent, expression, samSuperType).build() val loweredFunctionReference = FunctionReferenceBuilder(irFile, parent, expression, samSuperType).build()
generatedClasses.add(loweredFunctionReference.functionReferenceClass) generatedClasses.add(loweredFunctionReference.functionReferenceClass)
val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol,
expression.startOffset, expression.endOffset) expression.startOffset, expression.endOffset)
@@ -177,10 +175,12 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
private val getContinuationSymbol = symbols.getContinuation private val getContinuationSymbol = symbols.getContinuation
private val continuationClassSymbol = getContinuationSymbol.owner.returnType.classifierOrFail as IrClassSymbol private val continuationClassSymbol = getContinuationSymbol.owner.returnType.classifierOrFail as IrClassSymbol
private inner class FunctionReferenceBuilder(val parent: IrDeclarationParent, private inner class FunctionReferenceBuilder(
val functionReference: IrFunctionReference, val irFile: IrFile,
val samSuperType: IrType?) { val parent: IrDeclarationParent,
val functionReference: IrFunctionReference,
val samSuperType: IrType?
) {
private val startOffset = functionReference.startOffset private val startOffset = functionReference.startOffset
private val endOffset = functionReference.endOffset private val endOffset = functionReference.endOffset
private val referencedFunction = functionReference.symbol.owner private val referencedFunction = functionReference.symbol.owner
@@ -359,6 +359,7 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
type = parameter.type.substitute(typeArgumentsMap)) type = parameter.type.substitute(typeArgumentsMap))
} }
val kTypeGenerator = KTypeGenerator(context, irFile, functionReference)
body = context.createIrBuilder(symbol, startOffset, endOffset).irBlockBody { body = context.createIrBuilder(symbol, startOffset, endOffset).irBlockBody {
val superConstructor = when { val superConstructor = when {
isKSuspendFunction -> kSuspendFunctionImplConstructorSymbol.owner isKSuspendFunction -> kSuspendFunctionImplConstructorSymbol.owner
@@ -388,9 +389,6 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
} }
} }
private val IrFunction.fullName: String
get() = parent.fqNameForIrSerialization.child(Name.identifier(functionName)).asString()
private fun getFlags() = private fun getFlags() =
(if (referencedFunction.isSuspend) 1 else 0) + getAdaptedCallableReferenceFlags() shl 1 (if (referencedFunction.isSuspend) 1 else 0) + getAdaptedCallableReferenceFlags() shl 1
@@ -6,18 +6,16 @@
package org.jetbrains.kotlin.backend.konan.lower package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer
import org.jetbrains.kotlin.backend.common.lower.at
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.renderCompilerError import org.jetbrains.kotlin.backend.konan.renderCompilerError
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.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
/** /**
@@ -29,41 +27,31 @@ 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 : IrBuildingTransformer(context) {
override fun visitClassReference(expression: IrClassReference): IrExpression { override fun visitClassReference(expression: IrClassReference): IrExpression {
expression.transformChildrenVoid() expression.transformChildrenVoid()
val builder = createIrBuilder(expression) return builder.at(expression).run {
(expression.symbol as? IrClassSymbol)?.let { irKClass(this@PostInlineLowering.context, it) }
val symbol = expression.symbol ?:
return if (symbol is IrClassSymbol) { // E.g. for `T::class` in a body of an inline function itself.
builder.irKClass(context, symbol) irCall(symbols.throwNullPointerException.owner)
} 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 = createIrBuilder(expression) return builder.at(expression).run {
irCall(symbols.kClassImplConstructor, listOf(expression.argument.type)).apply {
val typeInfo = irCall(symbols.getObjectTypeInfo).apply {
putValueArgument(0, expression.argument)
}
val typeArgument = expression.argument.type putValueArgument(0, typeInfo)
return builder.irCall(symbols.kClassImplConstructor, listOf(typeArgument)).apply {
val typeInfo = builder.irCall(symbols.getObjectTypeInfo).apply {
putValueArgument(0, expression.argument)
} }
putValueArgument(0, typeInfo)
} }
} }
@@ -94,20 +82,14 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
expression.startOffset, expression.endOffset, expression.startOffset, expression.endOffset,
context.irBuiltIns.stringType, context.irBuiltIns.stringType,
IrConstKind.String, builder.toString())) IrConstKind.String, builder.toString()))
} else if (expression.symbol.owner.isTypeOfIntrinsic()) { } else if (Symbols.isTypeOfIntrinsic(expression.symbol)) {
val type = expression.getTypeArgument(0) return with (KTypeGenerator(context, irFile, expression, needExactTypeParameters = true)) {
?: error(irFile, expression, "missing type argument") builder.at(expression).irKType(expression.getTypeArgument(0)!!, leaveReifiedForLater = false)
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
)
}) })
} }
} }
@@ -6,20 +6,27 @@
package org.jetbrains.kotlin.backend.konan.lower package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.common.lower.at
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.KonanConfigKeys import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
import org.jetbrains.kotlin.ir.expressions.IrBody import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.ir.types.isUnit
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.util.file
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
/** /**
* This pass runs before inlining and performs the following additional transformations over some operations: * This pass runs before inlining and performs the following additional transformations over some operations:
* - Assertion call removal. * - Assertion call removal.
* - First phase of typeOf intrinsic lowering.
*/ */
internal class PreInlineLowering(val context: Context) : BodyLoweringPass { internal class PreInlineLowering(val context: Context) : BodyLoweringPass {
@@ -29,19 +36,30 @@ internal class PreInlineLowering(val context: Context) : BodyLoweringPass {
private val enableAssertions = context.config.configuration.getBoolean(KonanConfigKeys.ENABLE_ASSERTIONS) private val enableAssertions = context.config.configuration.getBoolean(KonanConfigKeys.ENABLE_ASSERTIONS)
override fun lower(irBody: IrBody, container: IrDeclaration) { override fun lower(irBody: IrBody, container: IrDeclaration) {
irBody.transformChildrenVoid(object : IrBuildingTransformer(context) { irBody.transformChildren(object : IrElementTransformer<IrBuilderWithScope> {
override fun visitDeclaration(declaration: IrDeclarationBase, data: IrBuilderWithScope) =
super.visitDeclaration(declaration,
data = (declaration as? IrSymbolOwner)?.let { context.createIrBuilder(it.symbol, it.startOffset, it.endOffset) }
?: data
)
override fun visitCall(expression: IrCall): IrExpression { override fun visitCall(expression: IrCall, data: IrBuilderWithScope): IrExpression {
expression.transformChildrenVoid(this) expression.transformChildren(this, data)
// Replace assert() call with an empty composite if assertions are not enabled. return when {
if (!enableAssertions && expression.symbol in asserts) { !enableAssertions && expression.symbol in asserts -> {
assert(expression.type.isUnit()) // Replace assert() call with an empty composite if assertions are not enabled.
return IrCompositeImpl(expression.startOffset, expression.endOffset, expression.type) require(expression.type.isUnit())
IrCompositeImpl(expression.startOffset, expression.endOffset, expression.type)
}
Symbols.isTypeOfIntrinsic(expression.symbol) -> {
with (KTypeGenerator(context, container.file, expression, needExactTypeParameters = true)) {
data.at(expression).irKType(expression.getTypeArgument(0)!!, leaveReifiedForLater = true)
}
}
else -> expression
} }
return expression
} }
}) }, data = context.createIrBuilder((container as IrSymbolOwner).symbol, irBody.startOffset, irBody.endOffset))
} }
} }
@@ -10,94 +10,184 @@ 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.ir.typeWithoutArguments
import org.jetbrains.kotlin.backend.konan.isObjCClass import org.jetbrains.kotlin.backend.konan.isObjCClass
import org.jetbrains.kotlin.backend.konan.llvm.fullName
import org.jetbrains.kotlin.backend.konan.reportCompilationError
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrEnumEntry
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
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.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrGetEnumValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl 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.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.ir.util.*
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
import org.jetbrains.kotlin.types.Variance
internal class KTypeGenerator( internal class KTypeGenerator(
private val context: KonanBackendContext, val context: KonanBackendContext,
private val eraseTypeParameters: Boolean = false val irFile: IrFile,
val irElement: IrElement,
val needExactTypeParameters: Boolean = false
) { ) {
private val symbols = context.ir.symbols private val symbols = context.ir.symbols
fun IrBuilderWithScope.irKType(type: IrType): IrExpression = if (type !is IrSimpleType) { fun IrBuilderWithScope.irKType(type: IrType, leaveReifiedForLater: Boolean = false) =
// Represent as non-denotable type: irKType(type, leaveReifiedForLater, mutableSetOf())
irKTypeImpl(
kClassifier = irNull(),
irTypeArguments = emptyList(),
isMarkedNullable = false
)
} else {
val classifier = type.classifier
if (classifier is IrClassSymbol) { private class RecursiveBoundsException(message: String) : Throwable(message)
irKTypeImpl(
kClassifier = irKClass(classifier), private fun IrBuilderWithScope.irKType(
irTypeArguments = type.arguments, type: IrType,
isMarkedNullable = type.hasQuestionMark leaveReifiedForLater: Boolean,
seenTypeParameters: MutableSet<IrTypeParameter>
): IrExpression {
if (type !is IrSimpleType) {
// Represent as non-denotable type:
return irKTypeImpl(
kClassifier = irNull(),
irTypeArguments = emptyList(),
isMarkedNullable = false,
leaveReifiedForLater = leaveReifiedForLater,
seenTypeParameters = seenTypeParameters
) )
} else { }
if (eraseTypeParameters) { try {
irKType(context.irBuiltIns.anyNType) val kClassifier = when (val classifier = type.classifier) {
} else { is IrClassSymbol -> irKClass(classifier)
irCall(symbols.kTypeImplForGenerics.constructors.single()) is IrTypeParameterSymbol -> {
if (classifier.owner.isReified && leaveReifiedForLater) {
// Leave as is for reification.
return irCall(symbols.typeOf).apply { putTypeArgument(0, type) }
}
// Leave upper bounds of non-reified type parameters as is, even if they are reified themselves.
irKTypeParameter(classifier.owner, leaveReifiedForLater = false, seenTypeParameters = seenTypeParameters)
}
else -> TODO("Unexpected classifier: $classifier")
} }
return irKTypeImpl(
kClassifier = kClassifier,
irTypeArguments = type.arguments,
isMarkedNullable = type.hasQuestionMark,
leaveReifiedForLater = leaveReifiedForLater,
seenTypeParameters = seenTypeParameters
)
} catch (t: RecursiveBoundsException) {
if (needExactTypeParameters)
this@KTypeGenerator.context.reportCompilationError(t.message!!, irFile, irElement)
return irCall(symbols.kTypeImplForTypeParametersWithRecursiveBounds.constructors.single())
} }
} }
private fun IrBuilderWithScope.irKTypeImpl( private fun IrBuilderWithScope.irKTypeImpl(
kClassifier: IrExpression, kClassifier: IrExpression,
irTypeArguments: List<IrTypeArgument>, irTypeArguments: List<IrTypeArgument>,
isMarkedNullable: Boolean isMarkedNullable: Boolean,
leaveReifiedForLater: Boolean,
seenTypeParameters: MutableSet<IrTypeParameter>
): IrExpression = irCall(symbols.kTypeImpl.constructors.single()).apply { ): IrExpression = irCall(symbols.kTypeImpl.constructors.single()).apply {
putValueArgument(0, kClassifier) putValueArgument(0, kClassifier)
putValueArgument(1, irKTypeProjectionsList(irTypeArguments)) putValueArgument(1, irKTypeProjectionsList(irTypeArguments, leaveReifiedForLater, seenTypeParameters))
putValueArgument(2, irBoolean(isMarkedNullable)) putValueArgument(2, irBoolean(isMarkedNullable))
} }
private fun IrBuilderWithScope.irKClass(symbol: IrClassSymbol) = irKClass(this@KTypeGenerator.context, symbol) private fun IrBuilderWithScope.irKClass(symbol: IrClassSymbol) = irKClass(this@KTypeGenerator.context, symbol)
private fun IrBuilderWithScope.irKTypeProjectionsList( private fun IrBuilderWithScope.irKTypeParameter(
irTypeArguments: List<IrTypeArgument> typeParameter: IrTypeParameter,
leaveReifiedForLater: Boolean,
seenTypeParameters: MutableSet<IrTypeParameter>
): IrMemberAccessExpression<*> { ): IrMemberAccessExpression<*> {
val kTypeProjectionType = symbols.kTypeProjection.typeWithoutArguments if (!seenTypeParameters.add(typeParameter))
throw RecursiveBoundsException("Non-reified type parameters with recursive bounds are not supported yet: ${typeParameter.render()}")
val result = irCall(symbols.kTypeParameterImpl.constructors.single()).apply {
putValueArgument(0, irString(typeParameter.name.asString()))
putValueArgument(1, irString(typeParameter.parentUniqueName))
putValueArgument(2, irKTypeList(typeParameter.superTypes, leaveReifiedForLater, seenTypeParameters))
putValueArgument(3, irKVariance(typeParameter.variance))
putValueArgument(4, irBoolean(typeParameter.isReified))
}
seenTypeParameters.remove(typeParameter)
return result
}
return if (irTypeArguments.isEmpty()) { private val IrTypeParameter.parentUniqueName get() = when (val parent = parent) {
irCall(symbols.emptyList, listOf(kTypeProjectionType)) is IrFunction -> parent.fullName
} else { else -> parent.fqNameForIrSerialization.asString()
irCall(symbols.listOf, listOf(kTypeProjectionType)).apply { }
putValueArgument(0, IrVarargImpl(
startOffset, private val Variance.kVarianceName: String
endOffset, get() = when (this) {
type = symbols.array.typeWith(kTypeProjectionType), Variance.INVARIANT -> "INVARIANT"
varargElementType = kTypeProjectionType, Variance.IN_VARIANCE -> "IN"
elements = irTypeArguments.map { irKTypeProjection(it) } Variance.OUT_VARIANCE -> "OUT"
)) }
}
private fun IrBuilderWithScope.irKVariance(variance: Variance) =
IrGetEnumValueImpl(
startOffset, endOffset,
symbols.kVariance.defaultType,
symbols.kVariance.owner.declarations
.filterIsInstance<IrEnumEntry>()
.single { it.name.asString() == variance.kVarianceName }.symbol
)
private fun <T> IrBuilderWithScope.irKTypeLikeList(
types: List<T>,
itemType: IrType,
itemBuilder: (T) -> IrExpression
) = if (types.isEmpty()) {
irCall(symbols.emptyList, listOf(itemType))
} else {
irCall(symbols.listOf, listOf(itemType)).apply {
putValueArgument(0, IrVarargImpl(
startOffset, endOffset,
type = symbols.array.typeWith(itemType),
varargElementType = itemType,
elements = types.map { itemBuilder(it) }
))
} }
} }
private fun IrBuilderWithScope.irKTypeProjection(argument: IrTypeArgument): IrExpression { private fun IrBuilderWithScope.irKTypeList(
return when (argument) { types: List<IrType>,
is IrTypeProjection -> irCall(symbols.kTypeProjectionFactories.getValue(argument.variance)).apply { leaveReifiedForLater: Boolean,
dispatchReceiver = irGetObject(symbols.kTypeProjectionCompanion) seenTypeParameters: MutableSet<IrTypeParameter>
putValueArgument(0, irKType(argument.type)) ) = irKTypeLikeList(types, symbols.kType.defaultType) { irKType(it, leaveReifiedForLater, seenTypeParameters) }
}
is IrStarProjection -> irCall(symbols.kTypeProjectionStar.owner.getter!!).apply { private fun IrBuilderWithScope.irKTypeProjectionsList(
dispatchReceiver = irGetObject(symbols.kTypeProjectionCompanion) irTypeArguments: List<IrTypeArgument>,
} leaveReifiedForLater: Boolean,
seenTypeParameters: MutableSet<IrTypeParameter>
) = irKTypeLikeList(irTypeArguments, symbols.kTypeProjection.typeWithoutArguments) {
irKTypeProjection(it, leaveReifiedForLater, seenTypeParameters)
}
else -> error("Unexpected IrTypeArgument: $argument (${argument::class})") private fun IrBuilderWithScope.irKTypeProjection(
argument: IrTypeArgument,
leaveReifiedForLater: Boolean,
seenTypeParameters: MutableSet<IrTypeParameter>
) = when (argument) {
is IrTypeProjection -> irCall(symbols.kTypeProjectionFactories.getValue(argument.variance)).apply {
dispatchReceiver = irGetObject(symbols.kTypeProjectionCompanion)
putValueArgument(0, irKType(argument.type, leaveReifiedForLater, seenTypeParameters))
} }
is IrStarProjection -> irCall(symbols.kTypeProjectionStar.owner.getter!!).apply {
dispatchReceiver = irGetObject(symbols.kTypeProjectionCompanion)
}
else -> error("Unexpected IrTypeArgument: $argument (${argument::class})")
} }
} }
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.backend.konan.lower package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.common.ir.allParameters import org.jetbrains.kotlin.backend.common.ir.allParameters
import org.jetbrains.kotlin.backend.common.lower.Closure import org.jetbrains.kotlin.backend.common.lower.Closure
import org.jetbrains.kotlin.backend.common.lower.ClosureAnnotator import org.jetbrains.kotlin.backend.common.lower.ClosureAnnotator
@@ -21,9 +22,11 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.isFinalClass import org.jetbrains.kotlin.descriptors.isFinalClass
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
@@ -428,11 +431,11 @@ private class BackendChecker(val context: Context, val irFile: IrFile) : IrEleme
getUnboundReferencedFunction(expression.getValueArgument(2)!!) getUnboundReferencedFunction(expression.getValueArgument(2)!!)
?: reportError(expression, "${callee.fqNameForIrSerialization} must take an unbound, non-capturing function or lambda") ?: reportError(expression, "${callee.fqNameForIrSerialization} must take an unbound, non-capturing function or lambda")
} }
else -> when (callee.symbol) { else -> when {
symbols.createCleaner -> callee.symbol == symbols.createCleaner ->
getUnboundReferencedFunction(expression.getValueArgument(1)!!) getUnboundReferencedFunction(expression.getValueArgument(1)!!)
?: reportError(expression, "${callee.fqNameForIrSerialization} must take an unbound, non-capturing function or lambda") ?: reportError(expression, "${callee.fqNameForIrSerialization} must take an unbound, non-capturing function or lambda")
symbols.immutableBlobOf -> { callee.symbol == symbols.immutableBlobOf -> {
val args = expression.getValueArgument(0) val args = expression.getValueArgument(0)
?: reportError(expression, "expected at least one element") ?: reportError(expression, "expected at least one element")
val elements = (args as IrVararg).elements val elements = (args as IrVararg).elements
@@ -446,6 +449,8 @@ private class BackendChecker(val context: Context, val irFile: IrFile) : IrEleme
reportError(it, "incorrect value for binary data: $value") reportError(it, "incorrect value for binary data: $value")
} }
} }
Symbols.isTypeOfIntrinsic(callee.symbol) ->
checkIrKType(expression, expression.getTypeArgument(0)!!)
} }
} }
} }
@@ -486,6 +491,34 @@ private class BackendChecker(val context: Context, val irFile: IrFile) : IrEleme
val typeParameter = symbol.owner.typeParameters.single() val typeParameter = symbol.owner.typeParameters.single()
return getTypeArgument(typeParameter.index)!! return getTypeArgument(typeParameter.index)!!
} }
private fun checkIrKType(
irElement: IrElement,
type: IrType,
seenTypeParameters: MutableSet<IrTypeParameter> = mutableSetOf()
) {
if (type !is IrSimpleType)
return
val classifier = type.classifier
if (classifier is IrTypeParameterSymbol)
checkIrKTypeParameter(irElement, classifier.owner, seenTypeParameters)
type.arguments.forEach {
if (it is IrTypeProjection)
checkIrKType(irElement, it.type, seenTypeParameters)
}
}
private fun checkIrKTypeParameter(
irElement: IrElement,
typeParameter: IrTypeParameter,
seenTypeParameters: MutableSet<IrTypeParameter>
) {
if (!seenTypeParameters.add(typeParameter))
reportError(irElement, "Non-reified type parameters with recursive bounds are not supported yet: ${typeParameter.render()}")
typeParameter.superTypes.forEach { checkIrKType(irElement, it, seenTypeParameters) }
seenTypeParameters.remove(typeParameter)
}
} }
private fun BackendChecker.checkCanGenerateCCall(expression: IrCall, isInvoke: Boolean) { private fun BackendChecker.checkCanGenerateCCall(expression: IrCall, isInvoke: Boolean) {
@@ -387,10 +387,5 @@ 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 == StandardNames.KOTLIN_REFLECT_FQ_NAME
fun IrBuilderWithScope.irByte(value: Byte) = fun IrBuilderWithScope.irByte(value: Byte) =
IrConstImpl.byte(startOffset, endOffset, context.irBuiltIns.byteType, value) IrConstImpl.byte(startOffset, endOffset, context.irBuiltIns.byteType, value)
+4
View File
@@ -1732,6 +1732,10 @@ task ktype1(type: KonanLocalTest) {
source = "codegen/ktype/ktype1.kt" source = "codegen/ktype/ktype1.kt"
} }
task ktype_nonReified(type: KonanLocalTest) {
source = "codegen/ktype/nonReified.kt"
}
task associatedObjects1(type: KonanLocalTest) { task associatedObjects1(type: KonanLocalTest) {
source = "codegen/associatedObjects/associatedObjects1.kt" source = "codegen/associatedObjects/associatedObjects1.kt"
} }
+1 -1
View File
@@ -32,7 +32,7 @@ fun testBasics1() {
assertEquals("$pkg.C<kotlin.Int?>", kType<C<Int?>>().toString()) assertEquals("$pkg.C<kotlin.Int?>", kType<C<Int?>>().toString())
assertEquals("$pkg.C<$pkg.C<kotlin.Any>>", kType<C<C<Any>>>().toString()) assertEquals("$pkg.C<$pkg.C<kotlin.Any>>", kType<C<C<Any>>>().toString())
assertEquals("$pkg.C<kotlin.Any?>", kTypeForCWithTypeParameter<D>().toString()) assertEquals("$pkg.C<T>", kTypeForCWithTypeParameter<D>().toString())
assertEquals("$pkg.Object", kType<Object>().toString()) assertEquals("$pkg.Object", kType<Object>().toString())
assertEquals("$pkg.Outer.Friend", kType<Outer.Friend>().toString()) assertEquals("$pkg.Outer.Friend", kType<Outer.Friend>().toString())
} }
@@ -0,0 +1,78 @@
/*
* 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 codegen.ktype.nonReified
import kotlin.test.*
import kotlin.reflect.*
@OptIn(kotlin.ExperimentalStdlibApi::class)
fun <T> foo() = typeOf<List<T>>()
@Test
fun test_fun() {
val l = foo<Int>()
assertEquals(List::class, l.classifier)
val t = l.arguments.single().type!!.classifier
assertTrue(t is KTypeParameter)
assertFalse((t as KTypeParameter).isReified)
assertEquals("T", (t as KTypeParameter).name)
}
class C<T> {
@OptIn(kotlin.ExperimentalStdlibApi::class)
fun foo() = typeOf<List<T>>()
}
@Test
fun test_class() {
val l = C<Int>().foo()
assertEquals(List::class, l.classifier)
val t = l.arguments.single().type!!.classifier
assertTrue(t is KTypeParameter)
assertFalse((t as KTypeParameter).isReified)
assertEquals("T", (t as KTypeParameter).name)
}
@OptIn(kotlin.ExperimentalStdlibApi::class)
fun <T> bar1() = typeOf<List<T>>()
@OptIn(kotlin.ExperimentalStdlibApi::class)
fun <T> bar2() = typeOf<List<T>>()
class D {
@OptIn(kotlin.ExperimentalStdlibApi::class)
fun <T> bar1() = typeOf<List<T>>()
}
@Test
fun test_equality() {
val t1 = bar1<Int>().arguments.single().type!!.classifier
val t2 = bar2<Int>().arguments.single().type!!.classifier
val t3 = D().bar1<Int>().arguments.single().type!!.classifier
assertNotEquals(t1, t2)
assertNotEquals(t1, t3)
assertNotEquals(t2, t3)
assertEquals(t1, bar1<Int>().arguments.single().type!!.classifier)
assertEquals(t2, bar2<Int>().arguments.single().type!!.classifier)
assertEquals(t3, D().bar1<Int>().arguments.single().type!!.classifier)
}
@OptIn(kotlin.ExperimentalStdlibApi::class)
inline fun <reified T, R : T> reifiedUpperBound() = typeOf<List<R>>()
@Test
fun test_reifiedUpperBound() {
val l = reifiedUpperBound<Any, Any>()
assertEquals(List::class, l.classifier)
val r = l.arguments.single().type!!.classifier
assertTrue(r is KTypeParameter)
assertFalse((r as KTypeParameter).isReified)
assertEquals("R", (r as KTypeParameter).name)
val t = (r as KTypeParameter).upperBounds.single().classifier
assertTrue(t is KTypeParameter)
assertTrue((t as KTypeParameter).isReified)
assertEquals("T", (t as KTypeParameter).name)
}
@@ -0,0 +1,7 @@
import kotlin.reflect.*
@OptIn(kotlin.ExperimentalStdlibApi::class)
fun <T : Comparable<T>> foo() {
typeOf<List<T>>()
}
@@ -0,0 +1,7 @@
import kotlin.reflect.*
@OptIn(kotlin.ExperimentalStdlibApi::class)
inline fun <reified T : Comparable<T>> foo() {
typeOf<List<T>>()
}
@@ -25,6 +25,7 @@ internal class KTypeImpl(
override fun toString(): String { override fun toString(): String {
val classifierString = when (classifier) { val classifierString = when (classifier) {
is KClass<*> -> classifier.qualifiedName ?: classifier.simpleName is KClass<*> -> classifier.qualifiedName ?: classifier.simpleName
is KTypeParameter -> classifier.name
else -> null else -> null
} ?: return "(non-denotable type)" } ?: return "(non-denotable type)"
@@ -37,16 +38,7 @@ internal class KTypeImpl(
arguments.forEachIndexed { index, argument -> arguments.forEachIndexed { index, argument ->
if (index > 0) append(", ") if (index > 0) append(", ")
if (argument.variance == null) { append(argument)
append('*')
} else {
append(when (argument.variance) {
KVariance.INVARIANT -> ""
KVariance.IN -> "in "
KVariance.OUT -> "out "
})
append(argument.type)
}
} }
append('>') append('>')
@@ -57,18 +49,18 @@ internal class KTypeImpl(
} }
} }
internal class KTypeImplForGenerics : KType { internal class KTypeImplForTypeParametersWithRecursiveBounds : KType {
override val classifier: KClassifier? override val classifier: KClassifier?
get() = error("Generic types are not yet supported in reflection") get() = error("Type parameters with recursive bounds are not yet supported in reflection")
override val arguments: List<KTypeProjection> get() = emptyList() 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("Type parameters with recursive bounds are not yet supported in reflection")
override fun equals(other: Any?) = override fun equals(other: Any?) =
error("Generic types are not yet supported in reflection") error("Type parameters with recursive bounds are not yet supported in reflection")
override fun hashCode(): Int = override fun hashCode(): Int =
error("Generic types are not yet supported in reflection") error("Type parameters with recursive bounds are not yet supported in reflection")
} }
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2020 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.native.internal
import kotlin.reflect.*
internal class KTypeParameterImpl(
override val name: String,
private val containerFqName: String,
override val upperBounds: List<KType>,
override val variance: KVariance,
override val isReified: Boolean
) : KTypeParameter {
override fun toString(): String = when (variance) {
KVariance.INVARIANT -> ""
KVariance.IN -> "in "
KVariance.OUT -> "out "
} + name
override fun equals(other: Any?) =
other is KTypeParameterImpl && name == other.name && containerFqName == other.containerFqName
override fun hashCode() = containerFqName.hashCode() * 31 + name.hashCode()
}