[IR] Supported non-reified typeOf
This commit is contained in:
+7
-7
@@ -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",
|
||||||
|
|||||||
+4
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-1
@@ -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)
|
||||||
|
|
||||||
|
|||||||
+2
@@ -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 }
|
||||||
|
|
||||||
|
|||||||
+10
-5
@@ -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(
|
||||||
|
|||||||
+9
-11
@@ -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
|
||||||
|
|
||||||
|
|||||||
+19
-37
@@ -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
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+30
-12
@@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+139
-49
@@ -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})")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+36
-3
@@ -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)
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user