Move most of ir utils from backend.common to ir.tree

This commit is contained in:
Ivan Kylchik
2022-02-24 20:41:49 +03:00
parent 40d224d5fe
commit f3252334b2
173 changed files with 857 additions and 1083 deletions
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir
import org.jetbrains.kotlin.ir.expressions.IrLoop
import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols
import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper
import org.jetbrains.kotlin.ir.util.DeepCopyTypeRemapper
import org.jetbrains.kotlin.ir.util.NullDescriptorsRemapper
import org.jetbrains.kotlin.ir.visitors.acceptVoid
@Suppress("UNCHECKED_CAST")
fun <T : IrElement> T.deepCopyWithVariables(): T {
val symbolsRemapper = DeepCopySymbolRemapper(NullDescriptorsRemapper)
acceptVoid(symbolsRemapper)
val typesRemapper = DeepCopyTypeRemapper(symbolsRemapper)
return this.transform(
object : DeepCopyIrTreeWithSymbols(symbolsRemapper, typesRemapper) {
override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop {
return irLoop
}
},
null
) as T
}
@@ -18,13 +18,16 @@ package org.jetbrains.kotlin.ir.builders
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrContainerExpression
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.declarations.buildVariable
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.util.*
@@ -176,3 +179,60 @@ inline fun IrGeneratorWithScope.irBlockBody(
endOffset
).blockBody(body)
fun IrBuilderWithScope.irWhile(origin: IrStatementOrigin? = null) =
IrWhileLoopImpl(startOffset, endOffset, context.irBuiltIns.unitType, origin)
fun IrBuilderWithScope.irDoWhile(origin: IrStatementOrigin? = null) =
IrDoWhileLoopImpl(startOffset, endOffset, context.irBuiltIns.unitType, origin)
fun IrBuilderWithScope.irBreak(loop: IrLoop) =
IrBreakImpl(startOffset, endOffset, context.irBuiltIns.nothingType, loop)
fun IrBuilderWithScope.irContinue(loop: IrLoop) =
IrContinueImpl(startOffset, endOffset, context.irBuiltIns.nothingType, loop)
fun IrBuilderWithScope.irGetObject(classSymbol: IrClassSymbol) =
IrGetObjectValueImpl(startOffset, endOffset, IrSimpleTypeImpl(classSymbol, false, emptyList(), emptyList()), classSymbol)
// Also adds created variable into building block
fun <T : IrElement> IrStatementsBuilder<T>.createTmpVariable(
irExpression: IrExpression,
nameHint: String? = null,
isMutable: Boolean = false,
origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
irType: IrType? = null
): IrVariable {
val variable = scope.createTmpVariable(irExpression, nameHint, isMutable, origin, irType)
+variable
return variable
}
fun Scope.createTmpVariable(
irType: IrType,
nameHint: String? = null,
isMutable: Boolean = false,
initializer: IrExpression? = null,
origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
startOffset: Int = UNDEFINED_OFFSET,
endOffset: Int = UNDEFINED_OFFSET
): IrVariable =
buildVariable(
getLocalDeclarationParent(), startOffset, endOffset, origin, Name.identifier(nameHint ?: "tmp"),
irType, isMutable
).apply {
this.initializer = initializer
}
fun Scope.createTmpVariable(
irExpression: IrExpression,
nameHint: String? = null,
isMutable: Boolean = false,
origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
irType: IrType? = null
): IrVariable =
buildVariable(
getLocalDeclarationParent(), irExpression.startOffset, irExpression.endOffset, origin, Name.identifier(nameHint ?: "tmp"),
irType ?: irExpression.type, isMutable
).apply {
initializer = irExpression
}
@@ -0,0 +1,339 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.builders.declarations
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
import org.jetbrains.kotlin.ir.symbols.impl.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.copyTo
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.types.Variance
@PublishedApi
internal fun IrFactory.buildClass(builder: IrClassBuilder): IrClass = with(builder) {
createClass(
startOffset, endOffset, origin,
IrClassSymbolImpl(),
name, kind, visibility, modality,
isCompanion, isInner, isData, isExternal, isValue, isExpect, isFun
)
}
inline fun IrFactory.buildClass(builder: IrClassBuilder.() -> Unit) =
IrClassBuilder().run {
builder()
buildClass(this)
}
@PublishedApi
internal fun IrFactory.buildField(builder: IrFieldBuilder): IrField = with(builder) {
createField(
startOffset, endOffset, origin,
IrFieldSymbolImpl(),
name, type, visibility, isFinal, isExternal, isStatic,
).also {
it.metadata = metadata
}
}
inline fun IrFactory.buildField(builder: IrFieldBuilder.() -> Unit) =
IrFieldBuilder().run {
builder()
buildField(this)
}
inline fun IrClass.addField(builder: IrFieldBuilder.() -> Unit) =
factory.buildField(builder).also { field ->
field.parent = this
declarations.add(field)
}
fun IrClass.addField(fieldName: Name, fieldType: IrType, fieldVisibility: DescriptorVisibility = DescriptorVisibilities.PRIVATE): IrField =
addField {
name = fieldName
type = fieldType
visibility = fieldVisibility
}
fun IrClass.addField(
fieldName: String,
fieldType: IrType,
fieldVisibility: DescriptorVisibility = DescriptorVisibilities.PRIVATE
): IrField =
addField(Name.identifier(fieldName), fieldType, fieldVisibility)
@PublishedApi
internal fun IrFactory.buildProperty(builder: IrPropertyBuilder): IrProperty = with(builder) {
createProperty(
startOffset, endOffset, origin,
IrPropertySymbolImpl(),
name, visibility, modality,
isVar, isConst, isLateinit, isDelegated, isExternal, isExpect, isFakeOverride,
containerSource,
)
}
inline fun IrFactory.buildProperty(builder: IrPropertyBuilder.() -> Unit) =
IrPropertyBuilder().run {
builder()
buildProperty(this)
}
inline fun IrClass.addProperty(builder: IrPropertyBuilder.() -> Unit): IrProperty =
factory.buildProperty(builder).also { property ->
declarations.add(property)
property.parent = this@addProperty
}
inline fun IrProperty.addGetter(builder: IrFunctionBuilder.() -> Unit = {}): IrSimpleFunction =
IrFunctionBuilder().run {
name = Name.special("<get-${this@addGetter.name}>")
builder()
factory.buildFunction(this).also { getter ->
this@addGetter.getter = getter
getter.correspondingPropertySymbol = this@addGetter.symbol
getter.parent = this@addGetter.parent
}
}
fun IrProperty.addDefaultGetter(parentClass: IrClass, builtIns: IrBuiltIns) {
val field = backingField!!
addGetter {
origin = IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
returnType = field.type
}.apply {
dispatchReceiverParameter = parentClass.thisReceiver!!.copyTo(this)
body = factory.createBlockBody(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf(
IrReturnImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
builtIns.nothingType,
symbol,
IrGetFieldImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
field.symbol,
field.type,
IrGetValueImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
dispatchReceiverParameter!!.type,
dispatchReceiverParameter!!.symbol
)
)
)
)
)
}
}
@PublishedApi
internal fun IrFactory.buildFunction(builder: IrFunctionBuilder): IrSimpleFunction = with(builder) {
createFunction(
startOffset, endOffset, origin,
IrSimpleFunctionSymbolImpl(),
name, visibility, modality, returnType,
isInline, isExternal, isTailrec, isSuspend, isOperator, isInfix, isExpect, isFakeOverride,
containerSource,
)
}
@PublishedApi
internal fun IrFactory.buildConstructor(builder: IrFunctionBuilder): IrConstructor = with(builder) {
return createConstructor(
startOffset, endOffset, origin,
IrConstructorSymbolImpl(),
SpecialNames.INIT,
visibility, returnType,
isInline = isInline, isExternal = isExternal, isPrimary = isPrimary, isExpect = isExpect,
containerSource = containerSource
)
}
inline fun IrFactory.buildFun(builder: IrFunctionBuilder.() -> Unit): IrSimpleFunction =
IrFunctionBuilder().run {
builder()
buildFunction(this)
}
inline fun IrFactory.addFunction(klass: IrDeclarationContainer, builder: IrFunctionBuilder.() -> Unit): IrSimpleFunction =
buildFun(builder).also { function ->
klass.declarations.add(function)
function.parent = klass
}
inline fun IrClass.addFunction(builder: IrFunctionBuilder.() -> Unit): IrSimpleFunction =
factory.addFunction(this, builder)
fun IrClass.addFunction(
name: String,
returnType: IrType,
modality: Modality = Modality.FINAL,
visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC,
isStatic: Boolean = false,
isSuspend: Boolean = false,
isFakeOverride: Boolean = false,
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED,
startOffset: Int = UNDEFINED_OFFSET,
endOffset: Int = UNDEFINED_OFFSET
): IrSimpleFunction =
addFunction {
this.startOffset = startOffset
this.endOffset = endOffset
this.name = Name.identifier(name)
this.returnType = returnType
this.modality = modality
this.visibility = visibility
this.isSuspend = isSuspend
this.isFakeOverride = isFakeOverride
this.origin = origin
}.apply {
if (!isStatic) {
val thisReceiver = parentAsClass.thisReceiver!!
dispatchReceiverParameter = thisReceiver.copyTo(this, type = thisReceiver.type)
}
}
inline fun IrFactory.buildConstructor(builder: IrFunctionBuilder.() -> Unit): IrConstructor =
IrFunctionBuilder().run {
builder()
buildConstructor(this)
}
inline fun IrClass.addConstructor(builder: IrFunctionBuilder.() -> Unit = {}): IrConstructor =
factory.buildConstructor {
builder()
returnType = defaultType
}.also { constructor ->
declarations.add(constructor)
constructor.parent = this@addConstructor
}
fun <D> buildReceiverParameter(
parent: D,
origin: IrDeclarationOrigin,
type: IrType,
startOffset: Int = parent.startOffset,
endOffset: Int = parent.endOffset
): IrValueParameter
where D : IrDeclaration, D : IrDeclarationParent =
parent.factory.createValueParameter(
startOffset, endOffset, origin,
IrValueParameterSymbolImpl(),
SpecialNames.THIS, -1, type, null, isCrossinline = false, isNoinline = false,
isHidden = false, isAssignable = false
).also {
it.parent = parent
}
fun IrFactory.buildValueParameter(builder: IrValueParameterBuilder, parent: IrDeclarationParent): IrValueParameter =
with(builder) {
return createValueParameter(
startOffset, endOffset, origin,
IrValueParameterSymbolImpl(),
name, index, type, varargElementType, isCrossInline, isNoinline, isHidden, isAssignable
).also {
it.parent = parent
}
}
inline fun <D> buildValueParameter(declaration: D, builder: IrValueParameterBuilder.() -> Unit): IrValueParameter
where D : IrDeclaration, D : IrDeclarationParent =
IrValueParameterBuilder().run {
builder()
declaration.factory.buildValueParameter(this, declaration)
}
inline fun IrFunction.addValueParameter(builder: IrValueParameterBuilder.() -> Unit): IrValueParameter =
IrValueParameterBuilder().run {
builder()
if (index == UNDEFINED_PARAMETER_INDEX) {
index = valueParameters.size
}
factory.buildValueParameter(this, this@addValueParameter).also { valueParameter ->
valueParameters = valueParameters + valueParameter
}
}
fun IrFunction.addValueParameter(name: String, type: IrType, origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED): IrValueParameter =
addValueParameter(Name.identifier(name), type, origin)
fun IrFunction.addValueParameter(name: Name, type: IrType, origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED): IrValueParameter =
addValueParameter {
this.name = name
this.type = type
this.origin = origin
}
@PublishedApi
internal fun IrFactory.buildTypeParameter(builder: IrTypeParameterBuilder, parent: IrDeclarationParent): IrTypeParameter =
with(builder) {
createTypeParameter(
startOffset, endOffset, origin,
IrTypeParameterSymbolImpl(),
name, index, isReified, variance
).also {
it.superTypes = superTypes
it.parent = parent
}
}
inline fun buildTypeParameter(parent: IrTypeParametersContainer, builder: IrTypeParameterBuilder.() -> Unit): IrTypeParameter =
IrTypeParameterBuilder().run {
builder()
parent.factory.buildTypeParameter(this, parent)
}
inline fun IrTypeParametersContainer.addTypeParameter(builder: IrTypeParameterBuilder.() -> Unit): IrTypeParameter =
IrTypeParameterBuilder().run {
builder()
if (index == UNDEFINED_PARAMETER_INDEX) {
index = typeParameters.size
}
factory.buildTypeParameter(this, this@addTypeParameter).also { typeParameter ->
typeParameters = typeParameters + typeParameter
}
}
fun IrTypeParametersContainer.addTypeParameter(name: String, upperBound: IrType, variance: Variance = Variance.INVARIANT): IrTypeParameter =
addTypeParameter {
this.name = Name.identifier(name)
this.variance = variance
this.superTypes.add(upperBound)
}
fun buildVariable(
parent: IrDeclarationParent?,
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
name: Name,
type: IrType,
isVar: Boolean = false,
isConst: Boolean = false,
isLateinit: Boolean = false,
): IrVariable {
return IrVariableImpl(
startOffset, endOffset, origin,
IrVariableSymbolImpl(),
name, type, isVar, isConst, isLateinit
).also {
if (parent != null) {
it.parent = parent
}
}
}
@@ -1,589 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.descriptors
import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.BuiltInOperatorNames
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeBuilder
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.util.OperatorNameConventions
@ObsoleteDescriptorBasedAPI
class IrBuiltInsOverDescriptors(
val builtIns: KotlinBuiltIns,
private val typeTranslator: TypeTranslator,
val symbolTable: SymbolTable
) : IrBuiltIns() {
override val languageVersionSettings = typeTranslator.languageVersionSettings
private var _functionFactory: IrAbstractDescriptorBasedFunctionFactory? = null
var functionFactory: IrAbstractDescriptorBasedFunctionFactory
get() =
synchronized(this) {
if (_functionFactory == null) {
_functionFactory = IrDescriptorBasedFunctionFactory(this, symbolTable, typeTranslator)
}
_functionFactory!!
}
set(value) {
synchronized(this) {
if (_functionFactory != null) {
error("functionFactory already set")
} else {
_functionFactory = value
}
}
}
override val irFactory: IrFactory = symbolTable.irFactory
private val builtInsModule = builtIns.builtInsModule
private val packageFragmentDescriptor = IrBuiltinsPackageFragmentDescriptorImpl(builtInsModule, KOTLIN_INTERNAL_IR_FQN)
override val operatorsPackageFragment: IrExternalPackageFragment =
IrExternalPackageFragmentImpl(symbolTable.referenceExternalPackageFragment(packageFragmentDescriptor), KOTLIN_INTERNAL_IR_FQN)
private fun ClassDescriptor.toIrSymbol() = symbolTable.referenceClass(this)
private fun KotlinType.toIrType() = typeTranslator.translateType(this)
private fun defineOperator(
name: String, returnType: IrType, valueParameterTypes: List<IrType>, isIntrinsicConst: Boolean = false
): IrSimpleFunctionSymbol {
val operatorDescriptor =
IrSimpleBuiltinOperatorDescriptorImpl(packageFragmentDescriptor, Name.identifier(name), returnType.originalKotlinType!!)
for ((i, valueParameterType) in valueParameterTypes.withIndex()) {
operatorDescriptor.addValueParameter(
IrBuiltinValueParameterDescriptorImpl(
operatorDescriptor, Name.identifier("arg$i"), i, valueParameterType.originalKotlinType!!
)
)
}
val symbol = symbolTable.declareSimpleFunctionIfNotExists(operatorDescriptor) {
val operator = irFactory.createFunction(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
BUILTIN_OPERATOR,
it,
Name.identifier(name),
DescriptorVisibilities.PUBLIC,
Modality.FINAL,
returnType,
isInline = false,
isExternal = false,
isTailrec = false,
isSuspend = false,
isOperator = false,
isInfix = false,
isExpect = false,
isFakeOverride = false
)
operator.parent = operatorsPackageFragment
operatorsPackageFragment.declarations += operator
operator.valueParameters = valueParameterTypes.withIndex().map { (i, valueParameterType) ->
val valueParameterDescriptor = operatorDescriptor.valueParameters[i]
val valueParameterSymbol = IrValueParameterSymbolImpl(valueParameterDescriptor)
irFactory.createValueParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, valueParameterSymbol, Name.identifier("arg$i"), i,
valueParameterType, null, isCrossinline = false, isNoinline = false, isHidden = false, isAssignable = false
).apply {
parent = operator
}
}
if (isIntrinsicConst) {
operator.annotations += IrConstructorCallImpl.fromSymbolDescriptor(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, intrinsicConstType, intrinsicConstConstructor
)
}
operator
}
return symbol.symbol
}
private fun defineCheckNotNullOperator(): IrSimpleFunctionSymbol {
val name = Name.identifier("CHECK_NOT_NULL")
val typeParameterDescriptor: TypeParameterDescriptor
val valueParameterDescriptor: ValueParameterDescriptor
val returnKotlinType: SimpleType
val valueKotlinType: SimpleType
// Note: We still need a complete function descriptor here because `CHECK_NOT_NULL` is being substituted by psi2ir
val operatorDescriptor = SimpleFunctionDescriptorImpl.create(
packageFragmentDescriptor,
Annotations.EMPTY,
name,
CallableMemberDescriptor.Kind.SYNTHESIZED,
SourceElement.NO_SOURCE
).apply {
typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification(
this, Annotations.EMPTY, false, Variance.INVARIANT, Name.identifier("T0"),
0, SourceElement.NO_SOURCE, LockBasedStorageManager.NO_LOCKS
).apply {
addUpperBound(any)
setInitialized()
}
valueKotlinType = typeParameterDescriptor.typeConstructor.makeNullableType()
valueParameterDescriptor = ValueParameterDescriptorImpl(
this, null, 0, Annotations.EMPTY, Name.identifier("arg0"), valueKotlinType,
declaresDefaultValue = false, isCrossinline = false, isNoinline = false, varargElementType = null,
source = SourceElement.NO_SOURCE
)
returnKotlinType = typeParameterDescriptor.typeConstructor.makeNonNullType()
initialize(
null, null, listOf(), listOf(typeParameterDescriptor), listOf(valueParameterDescriptor), returnKotlinType,
Modality.FINAL, DescriptorVisibilities.PUBLIC
)
}
return symbolTable.declareSimpleFunctionIfNotExists(operatorDescriptor) { operatorSymbol ->
val typeParameter = symbolTable.declareGlobalTypeParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
BUILTIN_OPERATOR,
typeParameterDescriptor
).apply {
superTypes += anyType
}
val typeParameterSymbol = typeParameter.symbol
val returnIrType = IrSimpleTypeBuilder().run {
classifier = typeParameterSymbol
kotlinType = returnKotlinType
nullability = SimpleTypeNullability.DEFINITELY_NOT_NULL
buildSimpleType()
}
val valueIrType = IrSimpleTypeBuilder().run {
classifier = typeParameterSymbol
kotlinType = valueKotlinType
nullability = SimpleTypeNullability.MARKED_NULLABLE
buildSimpleType()
}
irFactory.createFunction(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR,
operatorSymbol, name,
DescriptorVisibilities.PUBLIC, Modality.FINAL,
returnIrType,
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isOperator = false, isInfix = false,
isExpect = false, isFakeOverride = false
).also { operator ->
operator.parent = operatorsPackageFragment
operatorsPackageFragment.declarations += operator
val valueParameterSymbol = IrValueParameterSymbolImpl(valueParameterDescriptor)
val valueParameter = irFactory.createValueParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, valueParameterSymbol, Name.identifier("arg0"), 0,
valueIrType, null, isCrossinline = false, isNoinline = false, isHidden = false, isAssignable = false
)
valueParameter.parent = operator
typeParameter.parent = operator
operator.valueParameters += valueParameter
operator.typeParameters += typeParameter
}
}.symbol
}
private fun defineComparisonOperator(name: String, operandType: IrType) =
defineOperator(name, booleanType, listOf(operandType, operandType), isIntrinsicConst = true)
private fun List<IrType>.defineComparisonOperatorForEachIrType(name: String) =
associate { it.classifierOrFail to defineComparisonOperator(name, it) }
val any = builtIns.anyType
override val anyType = any.toIrType()
override val anyClass = builtIns.any.toIrSymbol()
override val anyNType = anyType.makeNullable()
val intrinsicConst = builtIns.intrinsicConstEvaluationType
private val intrinsicConstType = intrinsicConst.toIrType()
private val intrinsicConstConstructor = symbolTable.referenceConstructor(builtIns.intrinsicConstEvaluation.constructors.single())
val bool = builtIns.booleanType
override val booleanType = bool.toIrType()
override val booleanClass = builtIns.boolean.toIrSymbol()
val char = builtIns.charType
override val charType = char.toIrType()
override val charClass = builtIns.char.toIrSymbol()
val number = builtIns.number.defaultType
override val numberType = number.toIrType()
override val numberClass = builtIns.number.toIrSymbol()
val byte = builtIns.byteType
override val byteType = byte.toIrType()
override val byteClass = builtIns.byte.toIrSymbol()
val short = builtIns.shortType
override val shortType = short.toIrType()
override val shortClass = builtIns.short.toIrSymbol()
val int = builtIns.intType
override val intType = int.toIrType()
override val intClass = builtIns.int.toIrSymbol()
val long = builtIns.longType
override val longType = long.toIrType()
override val longClass = builtIns.long.toIrSymbol()
val float = builtIns.floatType
override val floatType = float.toIrType()
override val floatClass = builtIns.float.toIrSymbol()
val double = builtIns.doubleType
override val doubleType = double.toIrType()
override val doubleClass = builtIns.double.toIrSymbol()
val nothing = builtIns.nothingType
override val nothingType = nothing.toIrType()
override val nothingClass = builtIns.nothing.toIrSymbol()
override val nothingNType = nothingType.makeNullable()
val unit = builtIns.unitType
override val unitType = unit.toIrType()
override val unitClass = builtIns.unit.toIrSymbol()
val string = builtIns.stringType
override val stringType = string.toIrType()
override val stringClass = builtIns.string.toIrSymbol()
// TODO: check if correct
override val charSequenceClass = findClass(Name.identifier("CharSequence"), "kotlin")!!
override val collectionClass = builtIns.collection.toIrSymbol()
override val setClass = builtIns.set.toIrSymbol()
override val listClass = builtIns.list.toIrSymbol()
override val mapClass = builtIns.map.toIrSymbol()
override val mapEntryClass = builtIns.mapEntry.toIrSymbol()
override val iterableClass = builtIns.iterable.toIrSymbol()
override val iteratorClass = builtIns.iterator.toIrSymbol()
override val listIteratorClass = builtIns.listIterator.toIrSymbol()
override val mutableCollectionClass = builtIns.mutableCollection.toIrSymbol()
override val mutableSetClass = builtIns.mutableSet.toIrSymbol()
override val mutableListClass = builtIns.mutableList.toIrSymbol()
override val mutableMapClass = builtIns.mutableMap.toIrSymbol()
override val mutableMapEntryClass = builtIns.mutableMapEntry.toIrSymbol()
override val mutableIterableClass = builtIns.mutableIterable.toIrSymbol()
override val mutableIteratorClass = builtIns.mutableIterator.toIrSymbol()
override val mutableListIteratorClass = builtIns.mutableListIterator.toIrSymbol()
override val comparableClass = builtIns.comparable.toIrSymbol()
override val arrayClass = builtIns.array.toIrSymbol()
override val throwableType = builtIns.throwable.defaultType.toIrType()
override val throwableClass = builtIns.throwable.toIrSymbol()
override val kCallableClass = builtIns.kCallable.toIrSymbol()
override val kPropertyClass = builtIns.kProperty.toIrSymbol()
override val kClassClass = builtIns.kClass.toIrSymbol()
override val kProperty0Class = builtIns.kProperty0.toIrSymbol()
override val kProperty1Class = builtIns.kProperty1.toIrSymbol()
override val kProperty2Class = builtIns.kProperty2.toIrSymbol()
override val kMutableProperty0Class = builtIns.kMutableProperty0.toIrSymbol()
override val kMutableProperty1Class = builtIns.kMutableProperty1.toIrSymbol()
override val kMutableProperty2Class = builtIns.kMutableProperty2.toIrSymbol()
override val functionClass = builtIns.getBuiltInClassByFqName(FqName("kotlin.Function")).toIrSymbol()
override val kFunctionClass = builtIns.getBuiltInClassByFqName(FqName("kotlin.reflect.KFunction")).toIrSymbol()
override val annotationClass: IrClassSymbol = builtIns.annotation.toIrSymbol()
override val annotationType: IrType = builtIns.annotationType.toIrType()
override fun getKPropertyClass(mutable: Boolean, n: Int): IrClassSymbol = when (n) {
0 -> if (mutable) kMutableProperty0Class else kProperty0Class
1 -> if (mutable) kMutableProperty1Class else kProperty1Class
2 -> if (mutable) kMutableProperty2Class else kProperty2Class
else -> error("No KProperty for n=$n mutable=$mutable")
}
override val primitiveTypeToIrType = mapOf(
PrimitiveType.BOOLEAN to booleanType,
PrimitiveType.CHAR to charType,
PrimitiveType.BYTE to byteType,
PrimitiveType.SHORT to shortType,
PrimitiveType.INT to intType,
PrimitiveType.FLOAT to floatType,
PrimitiveType.LONG to longType,
PrimitiveType.DOUBLE to doubleType
)
// TODO switch to IrType
val primitiveTypes = listOf(bool, char, byte, short, int, float, long, double)
override val primitiveIrTypes = listOf(booleanType, charType, byteType, shortType, intType, floatType, longType, doubleType)
override val primitiveIrTypesWithComparisons = listOf(charType, byteType, shortType, intType, floatType, longType, doubleType)
override val primitiveFloatingPointIrTypes = listOf(floatType, doubleType)
override val byteArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.BYTE).toIrSymbol()
override val charArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.CHAR).toIrSymbol()
override val shortArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.SHORT).toIrSymbol()
override val intArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.INT).toIrSymbol()
override val longArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.LONG).toIrSymbol()
override val floatArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.FLOAT).toIrSymbol()
override val doubleArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.DOUBLE).toIrSymbol()
override val booleanArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.BOOLEAN).toIrSymbol()
override val primitiveArraysToPrimitiveTypes =
PrimitiveType.values().associate { builtIns.getPrimitiveArrayClassDescriptor(it).toIrSymbol() to it }
override val primitiveTypesToPrimitiveArrays = primitiveArraysToPrimitiveTypes.map { (k, v) -> v to k }.toMap()
override val primitiveArrayElementTypes = primitiveArraysToPrimitiveTypes.mapValues { primitiveTypeToIrType[it.value] }
override val primitiveArrayForType = primitiveArrayElementTypes.asSequence().associate { it.value to it.key }
override val unsignedTypesToUnsignedArrays: Map<UnsignedType, IrClassSymbol> =
UnsignedType.values().mapNotNull { unsignedType ->
val array = builtIns.builtInsModule.findClassAcrossModuleDependencies(unsignedType.arrayClassId)?.toIrSymbol()
if (array == null) null else unsignedType to array
}.toMap()
override val lessFunByOperandType = primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.LESS)
override val lessOrEqualFunByOperandType =
primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.LESS_OR_EQUAL)
override val greaterOrEqualFunByOperandType =
primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.GREATER_OR_EQUAL)
override val greaterFunByOperandType =
primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.GREATER)
override val ieee754equalsFunByOperandType =
primitiveFloatingPointIrTypes.map {
it.classifierOrFail to defineOperator(
BuiltInOperatorNames.IEEE754_EQUALS,
booleanType,
listOf(it.makeNullable(), it.makeNullable()),
isIntrinsicConst = true
)
}.toMap()
val booleanNot =
builtIns.boolean.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("not"), NoLookupLocation.FROM_BACKEND).single()
override val booleanNotSymbol = symbolTable.referenceSimpleFunction(booleanNot)
override val eqeqeqSymbol = defineOperator(BuiltInOperatorNames.EQEQEQ, booleanType, listOf(anyNType, anyNType))
override val eqeqSymbol = defineOperator(BuiltInOperatorNames.EQEQ, booleanType, listOf(anyNType, anyNType), isIntrinsicConst = true)
override val throwCceSymbol = defineOperator(BuiltInOperatorNames.THROW_CCE, nothingType, listOf())
override val throwIseSymbol = defineOperator(BuiltInOperatorNames.THROW_ISE, nothingType, listOf())
override val andandSymbol = defineOperator(BuiltInOperatorNames.ANDAND, booleanType, listOf(booleanType, booleanType), isIntrinsicConst = true)
override val ororSymbol = defineOperator(BuiltInOperatorNames.OROR, booleanType, listOf(booleanType, booleanType), isIntrinsicConst = true)
override val noWhenBranchMatchedExceptionSymbol =
defineOperator(BuiltInOperatorNames.NO_WHEN_BRANCH_MATCHED_EXCEPTION, nothingType, listOf())
override val illegalArgumentExceptionSymbol =
defineOperator(BuiltInOperatorNames.ILLEGAL_ARGUMENT_EXCEPTION, nothingType, listOf(stringType))
override val checkNotNullSymbol = defineCheckNotNullOperator()
private fun TypeConstructor.makeNonNullType() = KotlinTypeFactory.simpleType(TypeAttributes.Empty, this, listOf(), false)
private fun TypeConstructor.makeNullableType() = KotlinTypeFactory.simpleType(TypeAttributes.Empty, this, listOf(), true)
override val dataClassArrayMemberHashCodeSymbol = defineOperator("dataClassArrayMemberHashCode", intType, listOf(anyType))
override val dataClassArrayMemberToStringSymbol = defineOperator("dataClassArrayMemberToString", stringType, listOf(anyNType))
override val intTimesSymbol: IrSimpleFunctionSymbol =
builtIns.int.unsubstitutedMemberScope.findFirstFunction("times") {
KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, int)
}.let { symbolTable.referenceSimpleFunction(it) }
override val intXorSymbol: IrSimpleFunctionSymbol =
builtIns.int.unsubstitutedMemberScope.findFirstFunction("xor") {
KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, int)
}.let { symbolTable.referenceSimpleFunction(it) }
override val intPlusSymbol: IrSimpleFunctionSymbol =
builtIns.int.unsubstitutedMemberScope.findFirstFunction("plus") {
KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, int)
}.let { symbolTable.referenceSimpleFunction(it) }
override val arrayOf = findFunctions(Name.identifier("arrayOf")).first {
it.descriptor.extensionReceiverParameter == null && it.descriptor.dispatchReceiverParameter == null &&
it.descriptor.valueParameters.size == 1 && it.descriptor.valueParameters[0].varargElementType != null
}
override val arrayOfNulls = findFunctions(Name.identifier("arrayOfNulls")).first {
it.descriptor.extensionReceiverParameter == null && it.descriptor.dispatchReceiverParameter == null &&
it.descriptor.valueParameters.size == 1 && KotlinBuiltIns.isInt(it.descriptor.valueParameters[0].type)
}
override val linkageErrorSymbol: IrSimpleFunctionSymbol = defineOperator("linkageError", nothingType, listOf(stringType))
override val enumClass = builtIns.enum.toIrSymbol()
private fun builtInsPackage(vararg packageNameSegments: String) =
builtIns.builtInsModule.getPackage(FqName.fromSegments(listOf(*packageNameSegments))).memberScope
override fun findFunctions(name: Name, vararg packageNameSegments: String): Iterable<IrSimpleFunctionSymbol> =
builtInsPackage(*packageNameSegments).getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).map {
symbolTable.referenceSimpleFunction(it)
}
override fun findFunctions(name: Name, packageFqName: FqName): Iterable<IrSimpleFunctionSymbol> =
builtIns.builtInsModule.getPackage(packageFqName).memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).map {
symbolTable.referenceSimpleFunction(it)
}
override fun findClass(name: Name, vararg packageNameSegments: String): IrClassSymbol? =
(builtInsPackage(*packageNameSegments).getContributedClassifier(
name,
NoLookupLocation.FROM_BACKEND
) as? ClassDescriptor)?.let { symbolTable.referenceClass(it) }
override fun findClass(name: Name, packageFqName: FqName): IrClassSymbol? =
(builtIns.builtInsModule.getPackage(packageFqName).memberScope.getContributedClassifier(
name,
NoLookupLocation.FROM_BACKEND
) as? ClassDescriptor)?.let { symbolTable.referenceClass(it) }
override fun findBuiltInClassMemberFunctions(builtInClass: IrClassSymbol, name: Name): Iterable<IrSimpleFunctionSymbol> =
builtInClass.descriptor.unsubstitutedMemberScope
.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND)
.map { symbolTable.referenceSimpleFunction(it) }
private val binaryOperatorCache = mutableMapOf<Triple<Name, IrType, IrType>, IrSimpleFunctionSymbol>()
override fun getBinaryOperator(name: Name, lhsType: IrType, rhsType: IrType): IrSimpleFunctionSymbol {
require(lhsType is IrSimpleType) { "Expected IrSimpleType in getBinaryOperator, got $lhsType" }
val classifier = lhsType.classifier
require(classifier is IrClassSymbol && classifier.isBound) {
"Expected a bound IrClassSymbol for lhsType in getBinaryOperator, got $classifier"
}
val key = Triple(name, lhsType, rhsType)
return binaryOperatorCache.getOrPut(key) {
classifier.functions.single {
val function = it.owner
function.name == name && function.valueParameters.size == 1 && function.valueParameters[0].type == rhsType
}
}
}
private val unaryOperatorCache = mutableMapOf<Pair<Name, IrType>, IrSimpleFunctionSymbol>()
override fun getUnaryOperator(name: Name, receiverType: IrType): IrSimpleFunctionSymbol {
require(receiverType is IrSimpleType) { "Expected IrSimpleType in getBinaryOperator, got $receiverType" }
val classifier = receiverType.classifier
require(classifier is IrClassSymbol && classifier.isBound) {
"Expected a bound IrClassSymbol for receiverType in getBinaryOperator, got $classifier"
}
val key = Pair(name, receiverType)
return unaryOperatorCache.getOrPut(key) {
classifier.functions.single {
val function = it.owner
function.name == name && function.valueParameters.isEmpty()
}
}
}
private fun <T : Any> getFunctionsByKey(
name: Name,
vararg packageNameSegments: String,
makeKey: (SimpleFunctionDescriptor) -> T?
): Map<T, IrSimpleFunctionSymbol> {
val result = mutableMapOf<T, IrSimpleFunctionSymbol>()
for (d in builtInsPackage(*packageNameSegments).getContributedFunctions(name, NoLookupLocation.FROM_BACKEND)) {
makeKey(d)?.let { key ->
result[key] = symbolTable.referenceSimpleFunction(d)
}
}
return result
}
override fun getNonBuiltInFunctionsByExtensionReceiver(
name: Name, vararg packageNameSegments: String
): Map<IrClassifierSymbol, IrSimpleFunctionSymbol> =
getFunctionsByKey(name, *packageNameSegments) {
if (it.containingDeclaration !is BuiltInsPackageFragment && it.extensionReceiverParameter != null) {
symbolTable.referenceClassifier(it.extensionReceiverParameter!!.type.constructor.declarationDescriptor!!)
} else null
}
override fun getNonBuiltinFunctionsByReturnType(
name: Name, vararg packageNameSegments: String
): Map<IrClassifierSymbol, IrSimpleFunctionSymbol> =
getFunctionsByKey(Name.identifier("getProgressionLastElement"), *packageNameSegments) { d ->
if (d.containingDeclaration !is BuiltInsPackageFragment) {
d.returnType?.constructor?.declarationDescriptor?.let { symbolTable.referenceClassifier(it) }
} else null
}
override val extensionToString: IrSimpleFunctionSymbol = findFunctions(OperatorNameConventions.TO_STRING, "kotlin").first {
val descriptor = it.descriptor
descriptor is SimpleFunctionDescriptor && descriptor.dispatchReceiverParameter == null &&
descriptor.extensionReceiverParameter != null &&
KotlinBuiltIns.isNullableAny(descriptor.extensionReceiverParameter!!.type) && descriptor.valueParameters.isEmpty()
}
override val memberToString: IrSimpleFunctionSymbol = findBuiltInClassMemberFunctions(
anyClass,
OperatorNameConventions.TO_STRING
).single {
val descriptor = it.descriptor
descriptor is SimpleFunctionDescriptor && descriptor.valueParameters.isEmpty()
}
override val extensionStringPlus: IrSimpleFunctionSymbol = findFunctions(OperatorNameConventions.PLUS, "kotlin").first {
val descriptor = it.descriptor
descriptor is SimpleFunctionDescriptor && descriptor.dispatchReceiverParameter == null &&
descriptor.extensionReceiverParameter != null &&
KotlinBuiltIns.isStringOrNullableString(descriptor.extensionReceiverParameter!!.type) &&
descriptor.valueParameters.size == 1 &&
KotlinBuiltIns.isNullableAny(descriptor.valueParameters.first().type)
}
override val memberStringPlus: IrSimpleFunctionSymbol = findBuiltInClassMemberFunctions(
stringClass,
OperatorNameConventions.PLUS
).single {
val descriptor = it.descriptor
descriptor is SimpleFunctionDescriptor &&
descriptor.valueParameters.size == 1 &&
KotlinBuiltIns.isNullableAny(descriptor.valueParameters.first().type)
}
override fun functionN(arity: Int): IrClass = functionFactory.functionN(arity)
override fun kFunctionN(arity: Int): IrClass = functionFactory.kFunctionN(arity)
override fun suspendFunctionN(arity: Int): IrClass = functionFactory.suspendFunctionN(arity)
override fun kSuspendFunctionN(arity: Int): IrClass = functionFactory.kSuspendFunctionN(arity)
}
private inline fun MemberScope.findFirstFunction(name: String, predicate: (CallableMemberDescriptor) -> Boolean) =
getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).first(predicate)
@@ -1,479 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.descriptors
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.StandardNames.KOTLIN_REFLECT_FQ_NAME
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.SimpleTypeNullability
import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance
@OptIn(ObsoleteDescriptorBasedAPI::class)
abstract class IrAbstractDescriptorBasedFunctionFactory {
abstract fun functionClassDescriptor(arity: Int): FunctionClassDescriptor
abstract fun kFunctionClassDescriptor(arity: Int): FunctionClassDescriptor
abstract fun suspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor
abstract fun kSuspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor
abstract fun functionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass
abstract fun kFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass
abstract fun suspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass
abstract fun kSuspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass
fun functionN(n: Int) = functionN(n) { callback ->
val descriptor = functionClassDescriptor(n)
declareClass(descriptor) { symbol ->
callback(symbol)
}
}
fun kFunctionN(n: Int): IrClass {
return kFunctionN(n) { callback ->
val descriptor = kFunctionClassDescriptor(n)
declareClass(descriptor) { symbol ->
callback(symbol)
}
}
}
fun suspendFunctionN(n: Int): IrClass = suspendFunctionN(n) { callback ->
val descriptor = suspendFunctionClassDescriptor(n)
declareClass(descriptor) { symbol ->
callback(symbol)
}
}
fun kSuspendFunctionN(n: Int): IrClass = kSuspendFunctionN(n) { callback ->
val descriptor = kSuspendFunctionClassDescriptor(n)
declareClass(descriptor) { symbol ->
callback(symbol)
}
}
companion object {
val classOrigin = object : IrDeclarationOriginImpl("FUNCTION_INTERFACE_CLASS") {}
val memberOrigin = object : IrDeclarationOriginImpl("FUNCTION_INTERFACE_MEMBER") {}
const val offset = SYNTHETIC_OFFSET
internal fun functionClassName(isK: Boolean, isSuspend: Boolean, arity: Int): String =
"${if (isK) "K" else ""}${if (isSuspend) "Suspend" else ""}Function$arity"
}
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
class IrDescriptorBasedFunctionFactory(
private val irBuiltIns: IrBuiltInsOverDescriptors,
private val symbolTable: SymbolTable,
private val typeTranslator: TypeTranslator,
getPackageFragment: ((PackageFragmentDescriptor) -> IrPackageFragment)? = null,
// Needed for JS and Wasm backends to "preload" interfaces that can referenced during lowerings
private val referenceFunctionsWhenKFunctionAreReferenced: Boolean = false,
) : IrAbstractDescriptorBasedFunctionFactory() {
val getPackageFragment =
getPackageFragment ?: symbolTable::declareExternalPackageFragmentIfNotExists
// TODO: Lazieness
private val functionNMap = mutableMapOf<Int, IrClass>()
private val kFunctionNMap = mutableMapOf<Int, IrClass>()
private val suspendFunctionNMap = mutableMapOf<Int, IrClass>()
private val kSuspendFunctionNMap = mutableMapOf<Int, IrClass>()
private val irFactory: IrFactory get() = symbolTable.irFactory
val functionClass = symbolTable.referenceClass(irBuiltIns.builtIns.getBuiltInClassByFqName(FqName("kotlin.Function")))
val kFunctionClass = symbolTable.referenceClass(irBuiltIns.builtIns.getBuiltInClassByFqName(FqName("kotlin.reflect.KFunction")))
override fun functionClassDescriptor(arity: Int): FunctionClassDescriptor =
irBuiltIns.builtIns.getFunction(arity) as FunctionClassDescriptor
override fun suspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor =
irBuiltIns.builtIns.getSuspendFunction(arity) as FunctionClassDescriptor
override fun kFunctionClassDescriptor(arity: Int): FunctionClassDescriptor {
val kFunctionFqn = reflectFunctionClassFqn(reflectionFunctionClassName(false, arity))
return irBuiltIns.builtIns.getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor
}
override fun kSuspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor {
val kFunctionFqn = reflectFunctionClassFqn(reflectionFunctionClassName(true, arity))
return irBuiltIns.builtIns.getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor
}
override fun functionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
return functionNMap.getOrPut(arity) {
symbolTable.declarator { symbol ->
val descriptor = symbol.descriptor
val descriptorFactory = FunctionDescriptorFactory.RealDescriptorFactory(descriptor, symbolTable)
createFunctionClass(symbol, false, false, arity, irBuiltIns.functionClass, kotlinPackageFragment, descriptorFactory)
}
}
}
override fun suspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
return suspendFunctionNMap.getOrPut(arity) {
symbolTable.declarator { symbol ->
val descriptor = symbol.descriptor as FunctionClassDescriptor
val descriptorFactory = FunctionDescriptorFactory.RealDescriptorFactory(descriptor, symbolTable)
createFunctionClass(symbol, false, true, arity, irBuiltIns.functionClass, kotlinCoroutinesPackageFragment, descriptorFactory)
}
}
}
override fun kFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
if (referenceFunctionsWhenKFunctionAreReferenced)
functionN(arity)
return kFunctionNMap.getOrPut(arity) {
symbolTable.declarator { symbol ->
val descriptor = symbol.descriptor as FunctionClassDescriptor
val descriptorFactory = FunctionDescriptorFactory.RealDescriptorFactory(descriptor, symbolTable)
createFunctionClass(symbol, true, false, arity, irBuiltIns.kFunctionClass, kotlinReflectPackageFragment, descriptorFactory)
}
}
}
override fun kSuspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
if (referenceFunctionsWhenKFunctionAreReferenced)
suspendFunctionN(arity)
return kSuspendFunctionNMap.getOrPut(arity) {
symbolTable.declarator { symbol ->
val descriptor = symbol.descriptor as FunctionClassDescriptor
val descriptorFactory = FunctionDescriptorFactory.RealDescriptorFactory(descriptor, symbolTable)
createFunctionClass(symbol, true, true, arity, irBuiltIns.kFunctionClass, kotlinReflectPackageFragment, descriptorFactory)
}
}
}
private sealed class FunctionDescriptorFactory(protected val symbolTable: SymbolTable) {
abstract fun memberDescriptor(name: String, factory: (IrSimpleFunctionSymbol) -> IrSimpleFunction): IrSimpleFunctionSymbol
abstract fun FunctionDescriptor.valueParameterDescriptor(index: Int): ValueParameterDescriptor
abstract fun typeParameterDescriptor(index: Int, factory: (IrTypeParameterSymbol) -> IrTypeParameter): IrTypeParameterSymbol
abstract fun classReceiverParameterDescriptor(): ReceiverParameterDescriptor
class RealDescriptorFactory(private val classDescriptor: ClassDescriptor, symbolTable: SymbolTable) :
FunctionDescriptorFactory(symbolTable) {
override fun memberDescriptor(name: String, factory: (IrSimpleFunctionSymbol) -> IrSimpleFunction): IrSimpleFunctionSymbol {
val descriptor = classDescriptor.unsubstitutedMemberScope.run {
if (name[0] == '<') {
val propertyName = name.drop(5).dropLast(1)
val property = getContributedVariables(Name.identifier(propertyName), NoLookupLocation.FROM_BACKEND).single()
property.accessors.first { it.name.asString() == name }
} else {
getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).first()
}
}
return symbolTable.declareSimpleFunction(descriptor, factory).symbol
}
override fun FunctionDescriptor.valueParameterDescriptor(index: Int): ValueParameterDescriptor {
assert(containingDeclaration === classDescriptor)
return valueParameters[index]
}
override fun typeParameterDescriptor(index: Int, factory: (IrTypeParameterSymbol) -> IrTypeParameter): IrTypeParameterSymbol {
val descriptor = classDescriptor.declaredTypeParameters[index]
return symbolTable.declareGlobalTypeParameter(offset, offset, classOrigin, descriptor, factory).symbol
}
override fun classReceiverParameterDescriptor(): ReceiverParameterDescriptor {
return classDescriptor.thisAsReceiverParameter
}
}
}
private fun IrTypeParametersContainer.createTypeParameters(n: Int, descriptorFactory: FunctionDescriptorFactory): IrTypeParameter {
var index = 0
val typeParametersArray = ArrayList<IrTypeParameter>(n + 1)
for (i in 1 until (n + 1)) {
val pName = Name.identifier("P$i")
val pSymbol = descriptorFactory.typeParameterDescriptor(index) {
irFactory.createTypeParameter(
offset, offset, classOrigin, it, pName, index++, false, Variance.IN_VARIANCE
)
}
val pDeclaration = pSymbol.owner
pDeclaration.superTypes += irBuiltIns.anyNType
pDeclaration.parent = this
typeParametersArray.add(pDeclaration)
}
val rSymbol = descriptorFactory.typeParameterDescriptor(index) {
irFactory.createTypeParameter(
offset, offset, classOrigin, it, Name.identifier("R"), index, false, Variance.OUT_VARIANCE
)
}
val rDeclaration = rSymbol.owner
rDeclaration.superTypes += irBuiltIns.anyNType
rDeclaration.parent = this
typeParametersArray.add(rDeclaration)
typeParameters = typeParametersArray
return rDeclaration
}
private val kotlinPackageFragment: IrPackageFragment by lazy {
irBuiltIns.builtIns.getFunction(0).let {
getPackageFragment(it.containingDeclaration as PackageFragmentDescriptor)
}
}
private val kotlinCoroutinesPackageFragment: IrPackageFragment by lazy {
irBuiltIns.builtIns.getSuspendFunction(0).let {
getPackageFragment(it.containingDeclaration as PackageFragmentDescriptor)
}
}
private val kotlinReflectPackageFragment: IrPackageFragment by lazy {
irBuiltIns.kPropertyClass.descriptor.let {
getPackageFragment(it.containingDeclaration as PackageFragmentDescriptor)
}
}
private fun createThisReceiver(descriptorFactory: FunctionDescriptorFactory): IrValueParameter {
val descriptor = descriptorFactory.classReceiverParameterDescriptor()
return irFactory.createValueParameter(
offset, offset, classOrigin, IrValueParameterSymbolImpl(descriptor), SpecialNames.THIS, -1,
typeTranslator.translateType(descriptor.type), null,
isCrossinline = false,
isNoinline = false,
isHidden = false,
isAssignable = false
)
}
private fun IrClass.createMembers(isK: Boolean, isSuspend: Boolean, descriptorFactory: FunctionDescriptorFactory) {
if (!isK) {
val invokeSymbol = descriptorFactory.memberDescriptor("invoke") {
val returnType = with(IrSimpleTypeBuilder()) {
classifier = typeParameters.last().symbol
buildSimpleType()
}
irFactory.createFunction(
offset, offset, memberOrigin, it, Name.identifier("invoke"), DescriptorVisibilities.PUBLIC, Modality.ABSTRACT,
returnType,
isInline = false,
isExternal = false,
isTailrec = false,
isSuspend = isSuspend,
isOperator = true,
isInfix = false,
isExpect = false,
isFakeOverride = false
)
}
val fDeclaration = invokeSymbol.owner
fDeclaration.dispatchReceiverParameter = createThisReceiver(descriptorFactory).also { it.parent = fDeclaration }
val typeBuilder = IrSimpleTypeBuilder()
for (i in 1 until typeParameters.size) {
val vTypeParam = typeParameters[i - 1]
val vDescriptor = with(descriptorFactory) { invokeSymbol.descriptor.valueParameterDescriptor(i - 1) }
val vSymbol = IrValueParameterSymbolImpl(vDescriptor)
val vType = with(typeBuilder) {
classifier = vTypeParam.symbol
buildSimpleType()
}
val vDeclaration = irFactory.createValueParameter(
offset, offset, memberOrigin, vSymbol, Name.identifier("p$i"), i - 1, vType, null,
isCrossinline = false,
isNoinline = false,
isHidden = false,
isAssignable = false
)
vDeclaration.parent = fDeclaration
fDeclaration.valueParameters += vDeclaration
}
fDeclaration.parent = this
declarations += fDeclaration
}
// TODO: eventualy delegate it to fakeOverrideBuilder
addFakeOverrides()
}
private fun toIrType(wrapped: KotlinType): IrType {
val kotlinType = wrapped.unwrap()
return with(IrSimpleTypeBuilder()) {
classifier =
symbolTable.referenceClassifier(kotlinType.constructor.declarationDescriptor ?: error("No classifier for type $kotlinType"))
nullability = SimpleTypeNullability.fromHasQuestionMark(kotlinType.isMarkedNullable)
arguments = kotlinType.arguments.map {
if (it.isStarProjection) IrStarProjectionImpl
else makeTypeProjection(toIrType(it.type), it.projectionKind)
}
buildSimpleType()
}
}
private fun IrFunction.createValueParameter(descriptor: ParameterDescriptor): IrValueParameter = with(descriptor) {
irFactory.createValueParameter(
offset, offset, memberOrigin, IrValueParameterSymbolImpl(this), name, indexOrMinusOne, toIrType(type),
(this as? ValueParameterDescriptor)?.varargElementType?.let(::toIrType), isCrossinline, isNoinline, false, false
).also {
it.parent = this@createValueParameter
}
}
private fun IrClass.addFakeOverrides() {
val fakeOverrideDescriptors = descriptor.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.CALLABLES)
.filterIsInstance<CallableMemberDescriptor>().filter { it.kind === CallableMemberDescriptor.Kind.FAKE_OVERRIDE }
fun createFakeOverrideFunction(descriptor: FunctionDescriptor, property: IrPropertySymbol?): IrSimpleFunction {
val returnType = descriptor.returnType?.let { toIrType(it) } ?: error("No return type for $descriptor")
val newFunction = symbolTable.declareSimpleFunction(descriptor) {
descriptor.run {
irFactory.createFunction(
offset, offset, memberOrigin, it, name, visibility, modality, returnType,
isInline, isEffectivelyExternal(), isTailrec, isSuspend, isOperator, isInfix, isExpect, true
)
}
}
newFunction.parent = this
newFunction.overriddenSymbols = descriptor.overriddenDescriptors.map { symbolTable.referenceSimpleFunction(it.original) }
newFunction.dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.let { newFunction.createValueParameter(it) }
newFunction.extensionReceiverParameter = descriptor.extensionReceiverParameter?.let { newFunction.createValueParameter(it) }
newFunction.contextReceiverParametersCount = descriptor.contextReceiverParameters.size
newFunction.valueParameters = descriptor.valueParameters.map { newFunction.createValueParameter(it) }
newFunction.correspondingPropertySymbol = property
newFunction.annotations = descriptor.annotations.mapNotNull(
typeTranslator.constantValueGenerator::generateAnnotationConstructorCall
)
return newFunction
}
fun createFakeOverrideProperty(descriptor: PropertyDescriptor): IrProperty {
return symbolTable.declareProperty(offset, offset, memberOrigin, descriptor) {
irFactory.createProperty(
offset, offset, memberOrigin, it,
name = descriptor.name,
visibility = descriptor.visibility,
modality = descriptor.modality,
isVar = descriptor.isVar,
isConst = descriptor.isConst,
isLateinit = descriptor.isLateInit,
isDelegated = descriptor.isDelegated,
isExternal = descriptor.isEffectivelyExternal(),
isExpect = descriptor.isExpect
).apply {
parent = this@addFakeOverrides
getter = descriptor.getter?.let { g -> createFakeOverrideFunction(g, symbol) }
setter = descriptor.setter?.let { s -> createFakeOverrideFunction(s, symbol) }
annotations = descriptor.annotations.mapNotNull(
typeTranslator.constantValueGenerator::generateAnnotationConstructorCall
)
}
}
}
fun createFakeOverride(descriptor: CallableMemberDescriptor): IrDeclaration {
return when (descriptor) {
is FunctionDescriptor -> createFakeOverrideFunction(descriptor, null)
is PropertyDescriptor -> createFakeOverrideProperty(descriptor)
else -> error("Unexpected member $descriptor")
}
}
declarations += fakeOverrideDescriptors.map { createFakeOverride(it) }
}
private fun createFunctionClass(
symbol: IrClassSymbol,
isK: Boolean,
isSuspend: Boolean,
n: Int,
baseClass: IrClassSymbol,
packageFragment: IrPackageFragment,
descriptorFactory: FunctionDescriptorFactory
): IrClass {
val name = functionClassName(isK, isSuspend, n)
if (symbol.isBound) return symbol.owner
val klass = irFactory.createClass(
offset, offset, classOrigin, symbol, Name.identifier(name), ClassKind.INTERFACE, DescriptorVisibilities.PUBLIC, Modality.ABSTRACT
)
val r = klass.createTypeParameters(n, descriptorFactory)
klass.thisReceiver = createThisReceiver(descriptorFactory).also { it.parent = klass }
klass.superTypes = listOf(with(IrSimpleTypeBuilder()) {
classifier = baseClass
arguments = listOf(
with(IrSimpleTypeBuilder()) {
classifier = r.symbol
buildTypeProjection()
},
)
buildSimpleType()
})
klass.parent = packageFragment
packageFragment.declarations += klass
klass.createMembers(isK, isSuspend, descriptorFactory)
return klass
}
}
private fun reflectFunctionClassFqn(shortName: Name): FqName = KOTLIN_REFLECT_FQ_NAME.child(shortName)
private fun reflectionFunctionClassName(isSuspend: Boolean, arity: Int): Name =
Name.identifier("K${if (isSuspend) "Suspend" else ""}Function$arity")
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun KotlinBuiltIns.functionClassDescriptor(arity: Int): FunctionClassDescriptor =
getFunction(arity) as FunctionClassDescriptor
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun KotlinBuiltIns.suspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor =
getSuspendFunction(arity) as FunctionClassDescriptor
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun KotlinBuiltIns.kFunctionClassDescriptor(arity: Int): FunctionClassDescriptor {
val kFunctionFqn = reflectFunctionClassFqn(reflectionFunctionClassName(false, arity))
return getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun KotlinBuiltIns.kSuspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor {
val kFunctionFqn =
reflectFunctionClassFqn(reflectionFunctionClassName(true, arity))
return getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor
}
@@ -0,0 +1,169 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.builtins.StandardNames.FqNames
import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.DFS
val kotlinPackageFqn = FqName.fromSegments(listOf("kotlin"))
private val kotlinReflectionPackageFqn = kotlinPackageFqn.child(Name.identifier("reflect"))
private val kotlinCoroutinesPackageFqn = kotlinPackageFqn.child(Name.identifier("coroutines"))
fun IrType.isFunctionMarker(): Boolean = classifierOrNull?.isClassWithName("Function", kotlinPackageFqn) == true
fun IrType.isFunction(): Boolean = classifierOrNull?.isClassWithNamePrefix("Function", kotlinPackageFqn) == true
fun IrType.isKFunction(): Boolean = classifierOrNull?.isClassWithNamePrefix("KFunction", kotlinReflectionPackageFqn) == true
fun IrType.isSuspendFunction(): Boolean = classifierOrNull?.isClassWithNamePrefix("SuspendFunction", kotlinCoroutinesPackageFqn) == true
fun IrType.isKSuspendFunction(): Boolean = classifierOrNull?.isClassWithNamePrefix("KSuspendFunction", kotlinReflectionPackageFqn) == true
fun IrClassifierSymbol.isFunctionMarker(): Boolean = this.isClassWithName("Function", kotlinPackageFqn)
fun IrClassifierSymbol.isFunction(): Boolean = this.isClassWithNamePrefix("Function", kotlinPackageFqn)
fun IrClassifierSymbol.isKFunction(): Boolean = this.isClassWithNamePrefix("KFunction", kotlinReflectionPackageFqn)
fun IrClassifierSymbol.isSuspendFunction(): Boolean = this.isClassWithNamePrefix("SuspendFunction", kotlinCoroutinesPackageFqn)
fun IrClassifierSymbol.isKSuspendFunction(): Boolean = this.isClassWithNamePrefix("KSuspendFunction", kotlinReflectionPackageFqn)
private fun IrClassifierSymbol.isClassWithName(name: String, packageFqName: FqName): Boolean {
val declaration = owner as IrDeclarationWithName
return name == declaration.name.asString() && (declaration.parent as? IrPackageFragment)?.fqName == packageFqName
}
private fun IrClassifierSymbol.isClassWithNamePrefix(prefix: String, packageFqName: FqName): Boolean {
val declaration = owner as IrDeclarationWithName
return declaration.name.asString().startsWith(prefix) && (declaration.parent as? IrPackageFragment)?.fqName == packageFqName
}
fun IrType.superTypes(): List<IrType> = classifierOrNull?.superTypes() ?: emptyList()
fun IrType.isFunctionTypeOrSubtype(): Boolean = DFS.ifAny(listOf(this), IrType::superTypes, IrType::isFunction)
fun IrType.isSuspendFunctionTypeOrSubtype(): Boolean = DFS.ifAny(listOf(this), IrType::superTypes, IrType::isSuspendFunction)
fun IrType.isTypeParameter() = classifierOrNull is IrTypeParameterSymbol
fun IrType.isInterface() = classOrNull?.owner?.kind == ClassKind.INTERFACE
fun IrType.isAnnotation() = classOrNull?.owner?.kind == ClassKind.ANNOTATION_CLASS
fun IrType.isFunctionOrKFunction() = isFunction() || isKFunction()
fun IrType.isSuspendFunctionOrKFunction() = isSuspendFunction() || isKSuspendFunction()
fun IrType.isThrowable(): Boolean = isTypeFromKotlinPackage { name -> name.asString() == "Throwable" }
fun IrType.isUnsigned(): Boolean = isTypeFromKotlinPackage { name -> UnsignedTypes.isShortNameOfUnsignedType(name) }
fun IrType.isUnsignedArray(): Boolean = isTypeFromKotlinPackage { name -> UnsignedTypes.isShortNameOfUnsignedArray(name) }
private inline fun IrType.isTypeFromKotlinPackage(namePredicate: (Name) -> Boolean): Boolean {
if (this is IrSimpleType) {
val classClassifier = classifier as? IrClassSymbol ?: return false
if (!namePredicate(classClassifier.owner.name)) return false
val parent = classClassifier.owner.parent as? IrPackageFragment ?: return false
return parent.fqName == kotlinPackageFqn
} else return false
}
fun IrType.isPrimitiveArray() = isTypeFromKotlinPackage { it in FqNames.primitiveArrayTypeShortNames }
fun IrType.getPrimitiveArrayElementType() = (this as? IrSimpleType)?.let {
(it.classifier.owner as? IrClass)?.fqNameWhenAvailable?.toUnsafe()?.let { fqn -> FqNames.arrayClassFqNameToPrimitiveType[fqn] }
}
fun IrType.substitute(params: List<IrTypeParameter>, arguments: List<IrType>): IrType =
substitute(params.map { it.symbol }.zip(arguments).toMap())
fun IrType.substitute(substitutionMap: Map<IrTypeParameterSymbol, IrType>): IrType {
if (this !is IrSimpleType || substitutionMap.isEmpty()) return this
val newAnnotations = annotations.map { it.deepCopyWithSymbols() }
substitutionMap[classifier]?.let { substitutedType ->
// Add nullability and annotations from original type
return substitutedType
.mergeNullability(this)
.addAnnotations(newAnnotations)
}
val newArguments = arguments.map {
if (it is IrTypeProjection) {
makeTypeProjection(it.type.substitute(substitutionMap), it.variance)
} else {
it
}
}
return IrSimpleTypeImpl(
classifier,
nullability,
newArguments,
newAnnotations
)
}
private fun getImmediateSupertypes(irType: IrSimpleType): List<IrSimpleType> {
val irClass = irType.getClass()
?: throw AssertionError("Not a class type: ${irType.render()}")
val originalSupertypes = irClass.superTypes
val arguments =
irType.arguments.map {
it.typeOrNull
?: throw AssertionError("*-projection in supertype arguments: ${irType.render()}")
}
return originalSupertypes
.filter { it.classOrNull != null }
.map { superType ->
superType.substitute(irClass.typeParameters, arguments) as IrSimpleType
}
}
private fun collectAllSupertypes(irType: IrSimpleType, result: MutableSet<IrSimpleType>) {
val immediateSupertypes = getImmediateSupertypes(irType)
result.addAll(immediateSupertypes)
for (supertype in immediateSupertypes) {
collectAllSupertypes(supertype, result)
}
}
// Given the following classes:
// open class A<X>
// open class B<Y> : A<List<Y>>
// class C<Z> : B<List<Z>>
// for the class C, this function constructs:
// { B<List<Z>>, A<List<List<Z>>, Any }
// where Z is a type parameter of class C.
fun getAllSubstitutedSupertypes(irClass: IrClass): Set<IrSimpleType> {
val result = HashSet<IrSimpleType>()
collectAllSupertypes(irClass.defaultType, result)
return result
}
private fun collectAllSuperclasses(irClass: IrClass, set: MutableSet<IrClass>) {
for (superType in irClass.superTypes) {
val classifier = superType.classifierOrNull as? IrClassSymbol ?: continue
val superClass = classifier.owner
if (set.add(superClass)) {
collectAllSuperclasses(superClass, set)
}
}
}
fun IrClass.getAllSuperclasses(): Set<IrClass> {
val result = HashSet<IrClass>()
collectAllSuperclasses(this, result)
return result
}
@@ -7,16 +7,30 @@ package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.*
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
import org.jetbrains.kotlin.ir.builders.declarations.buildReceiverParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildTypeParameter
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy
import org.jetbrains.kotlin.ir.overrides.IrOverridingUtil
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrPropertySymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.io.StringWriter
/**
* Binds the arguments explicitly represented in the IR to the parameters of the accessed function.
@@ -623,3 +637,609 @@ val IrDeclarationParent.isFacadeClass: Boolean
(origin == IrDeclarationOrigin.JVM_MULTIFILE_CLASS ||
origin == IrDeclarationOrigin.FILE_CLASS ||
origin == IrDeclarationOrigin.SYNTHETIC_FILE_CLASS)
fun ir2string(ir: IrElement?): String = ir?.render() ?: ""
@Suppress("unused") // Used in kotlin-native
fun ir2stringWhole(ir: IrElement?): String {
val strWriter = StringWriter()
ir?.accept(DumpIrTreeVisitor(strWriter), "")
return strWriter.toString()
}
fun IrClass.addSimpleDelegatingConstructor(
superConstructor: IrConstructor,
irBuiltIns: IrBuiltIns,
isPrimary: Boolean = false,
origin: IrDeclarationOrigin? = null
): IrConstructor =
addConstructor {
val klass = this@addSimpleDelegatingConstructor
this.startOffset = klass.startOffset
this.endOffset = klass.endOffset
this.origin = origin ?: klass.origin
this.visibility = superConstructor.visibility
this.isPrimary = isPrimary
}.also { constructor ->
constructor.valueParameters = superConstructor.valueParameters.mapIndexed { index, parameter ->
parameter.copyTo(constructor, index = index)
}
constructor.body = factory.createBlockBody(
startOffset, endOffset,
listOf(
IrDelegatingConstructorCallImpl(
startOffset, endOffset, irBuiltIns.unitType,
superConstructor.symbol, 0,
superConstructor.valueParameters.size
).apply {
constructor.valueParameters.forEachIndexed { idx, parameter ->
putValueArgument(idx, IrGetValueImpl(startOffset, endOffset, parameter.type, parameter.symbol))
}
},
IrInstanceInitializerCallImpl(startOffset, endOffset, this.symbol, irBuiltIns.unitType)
)
)
}
val IrCall.isSuspend get() = (symbol.owner as? IrSimpleFunction)?.isSuspend == true
val IrFunctionReference.isSuspend get() = (symbol.owner as? IrSimpleFunction)?.isSuspend == true
val IrFunction.isOverridable get() = this is IrSimpleFunction && this.isOverridable
val IrSimpleFunction.isOverridable: Boolean
get() = visibility != DescriptorVisibilities.PRIVATE && modality != Modality.FINAL && (parent as? IrClass)?.isFinalClass != true
val IrFunction.isOverridableOrOverrides: Boolean get() = this is IrSimpleFunction && (isOverridable || overriddenSymbols.isNotEmpty())
val IrDeclaration.isMemberOfOpenClass: Boolean
get() {
val parentClass = this.parent as? IrClass ?: return false
return !parentClass.isFinalClass
}
val IrClass.isFinalClass: Boolean
get() = modality == Modality.FINAL && kind != ClassKind.ENUM_CLASS
val IrTypeParametersContainer.classIfConstructor get() = if (this is IrConstructor) parentAsClass else this
fun IrValueParameter.copyTo(
irFunction: IrFunction,
origin: IrDeclarationOrigin = this.origin,
index: Int = this.index,
startOffset: Int = this.startOffset,
endOffset: Int = this.endOffset,
name: Name = this.name,
remapTypeMap: Map<IrTypeParameter, IrTypeParameter> = mapOf(),
type: IrType = this.type.remapTypeParameters(
(parent as IrTypeParametersContainer).classIfConstructor,
irFunction.classIfConstructor,
remapTypeMap
),
varargElementType: IrType? = this.varargElementType, // TODO: remapTypeParameters here as well
defaultValue: IrExpressionBody? = this.defaultValue,
isCrossinline: Boolean = this.isCrossinline,
isNoinline: Boolean = this.isNoinline,
isAssignable: Boolean = this.isAssignable
): IrValueParameter {
val symbol = IrValueParameterSymbolImpl()
val defaultValueCopy = defaultValue?.let { originalDefault ->
factory.createExpressionBody(originalDefault.startOffset, originalDefault.endOffset) {
expression = originalDefault.expression.deepCopyWithVariables().also {
it.patchDeclarationParents(irFunction)
}
}
}
return factory.createValueParameter(
startOffset, endOffset, origin, symbol,
name, index, type, varargElementType, isCrossinline = isCrossinline,
isNoinline = isNoinline, isHidden = false, isAssignable = isAssignable
).also {
it.parent = irFunction
it.defaultValue = defaultValueCopy
it.copyAnnotationsFrom(this)
}
}
fun IrTypeParameter.copyToWithoutSuperTypes(
target: IrTypeParametersContainer,
index: Int = this.index,
origin: IrDeclarationOrigin = this.origin
): IrTypeParameter = buildTypeParameter(target) {
updateFrom(this@copyToWithoutSuperTypes)
this.name = this@copyToWithoutSuperTypes.name
this.origin = origin
this.index = index
}
fun IrFunction.copyReceiverParametersFrom(from: IrFunction, substitutionMap: Map<IrTypeParameterSymbol, IrType>) {
dispatchReceiverParameter = from.dispatchReceiverParameter?.run {
factory.createValueParameter(
startOffset, endOffset, origin,
IrValueParameterSymbolImpl(),
name, index,
type.substitute(substitutionMap),
varargElementType?.substitute(substitutionMap),
isCrossinline, isNoinline,
isHidden, isAssignable
).also { parameter ->
parameter.parent = this@copyReceiverParametersFrom
}
}
extensionReceiverParameter = from.extensionReceiverParameter?.copyTo(this)
}
fun IrFunction.copyValueParametersFrom(from: IrFunction, substitutionMap: Map<IrTypeParameterSymbol, IrType>) {
copyReceiverParametersFrom(from, substitutionMap)
val shift = valueParameters.size
valueParameters += from.valueParameters.map {
it.copyTo(this, index = it.index + shift, type = it.type.substitute(substitutionMap))
}
}
fun IrFunction.copyParameterDeclarationsFrom(from: IrFunction) {
assert(typeParameters.isEmpty())
copyTypeParametersFrom(from)
val substitutionMap = makeTypeParameterSubstitutionMap(from, this)
copyValueParametersFrom(from, substitutionMap)
}
fun IrTypeParametersContainer.copyTypeParameters(
srcTypeParameters: List<IrTypeParameter>,
origin: IrDeclarationOrigin? = null,
parameterMap: Map<IrTypeParameter, IrTypeParameter>? = null
): List<IrTypeParameter> {
val shift = typeParameters.size
val oldToNewParameterMap = parameterMap.orEmpty().toMutableMap()
// Any type parameter can figure in a boundary type for any other parameter.
// Therefore, we first copy the parameters themselves, then set up their supertypes.
val newTypeParameters = srcTypeParameters.mapIndexed { i, sourceParameter ->
sourceParameter.copyToWithoutSuperTypes(this, index = i + shift, origin = origin ?: sourceParameter.origin).also {
oldToNewParameterMap[sourceParameter] = it
}
}
typeParameters += newTypeParameters
srcTypeParameters.zip(newTypeParameters).forEach { (srcParameter, dstParameter) ->
dstParameter.copySuperTypesFrom(srcParameter, oldToNewParameterMap)
}
return newTypeParameters
}
fun IrTypeParametersContainer.copyTypeParametersFrom(
source: IrTypeParametersContainer,
origin: IrDeclarationOrigin? = null,
parameterMap: Map<IrTypeParameter, IrTypeParameter>? = null
) = copyTypeParameters(source.typeParameters, origin, parameterMap)
private fun IrTypeParameter.copySuperTypesFrom(source: IrTypeParameter, srcToDstParameterMap: Map<IrTypeParameter, IrTypeParameter>) {
val target = this
val sourceParent = source.parent as IrTypeParametersContainer
val targetParent = target.parent as IrTypeParametersContainer
target.superTypes = source.superTypes.map {
it.remapTypeParameters(sourceParent, targetParent, srcToDstParameterMap)
}
}
fun IrAnnotationContainer.copyAnnotations(): List<IrConstructorCall> {
return annotations.map { it.deepCopyWithSymbols(this as? IrDeclarationParent) }
}
fun IrAnnotationContainer.copyAnnotationsWhen(filter: IrConstructorCall.() -> Boolean): List<IrConstructorCall> {
return annotations.mapNotNull { if (it.filter()) it.deepCopyWithSymbols(this as? IrDeclarationParent) else null }
}
fun IrMutableAnnotationContainer.copyAnnotationsFrom(source: IrAnnotationContainer) {
annotations += source.copyAnnotations()
}
fun makeTypeParameterSubstitutionMap(
original: IrTypeParametersContainer,
transformed: IrTypeParametersContainer
): Map<IrTypeParameterSymbol, IrType> =
original.typeParameters
.map { it.symbol }
.zip(transformed.typeParameters.map { it.defaultType })
.toMap()
// Copy value parameters, dispatch receiver, and extension receiver from source to value parameters of this function.
// Type of dispatch receiver defaults to source's dispatch receiver. It is overridable in case the new function and the old one are used in
// different contexts and expect different type of dispatch receivers. The overriding type should be assign compatible to the old type.
fun IrFunction.copyValueParametersToStatic(
source: IrFunction,
origin: IrDeclarationOrigin,
dispatchReceiverType: IrType? = source.dispatchReceiverParameter?.type,
numValueParametersToCopy: Int = source.valueParameters.size
) {
val target = this
assert(target.valueParameters.isEmpty())
var shift = 0
source.dispatchReceiverParameter?.let { originalDispatchReceiver ->
assert(dispatchReceiverType!!.isSubtypeOfClass(originalDispatchReceiver.type.classOrNull!!))
val type = dispatchReceiverType.remapTypeParameters(
(originalDispatchReceiver.parent as IrTypeParametersContainer).classIfConstructor,
target.classIfConstructor
)
target.valueParameters += originalDispatchReceiver.copyTo(
target,
origin = originalDispatchReceiver.origin,
index = shift++,
type = type,
name = Name.identifier("\$this")
)
}
source.extensionReceiverParameter?.let { originalExtensionReceiver ->
target.valueParameters += originalExtensionReceiver.copyTo(
target,
origin = originalExtensionReceiver.origin,
index = shift++,
name = Name.identifier("\$receiver")
)
}
for (oldValueParameter in source.valueParameters) {
if (oldValueParameter.index >= numValueParametersToCopy) break
target.valueParameters += oldValueParameter.copyTo(
target,
origin = origin,
index = oldValueParameter.index + shift
)
}
}
fun IrFunctionAccessExpression.passTypeArgumentsFrom(irFunction: IrTypeParametersContainer, offset: Int = 0) {
irFunction.typeParameters.forEachIndexed { i, param ->
putTypeArgument(i + offset, param.defaultType)
}
}
/**
* Perform a substitution of type parameters occuring in [this]. In order of
* precedence, parameter `P` is substituted with...
*
* 1) `T`, if `srcToDstParameterMap.get(P) == T`
* 2) `T`, if `source.typeParameters[i] == P` and
* `target.typeParameters[i] == T`
* 3) `P`
*
* If [srcToDstParameterMap] is total on the domain of type parameters in
* [this], this effectively performs a substitution according to that map.
*/
fun IrType.remapTypeParameters(
source: IrTypeParametersContainer,
target: IrTypeParametersContainer,
srcToDstParameterMap: Map<IrTypeParameter, IrTypeParameter>? = null
): IrType =
when (this) {
is IrSimpleType -> {
val classifier = classifier.owner
when {
classifier is IrTypeParameter -> {
val newClassifier =
srcToDstParameterMap?.get(classifier) ?: if (classifier.parent == source)
target.typeParameters[classifier.index]
else
classifier
IrSimpleTypeImpl(newClassifier.symbol, nullability, arguments, annotations)
}
classifier is IrClass ->
IrSimpleTypeImpl(
classifier.symbol,
nullability,
arguments.map {
when (it) {
is IrTypeProjection -> makeTypeProjection(
it.type.remapTypeParameters(source, target, srcToDstParameterMap),
it.variance
)
else -> it
}
},
annotations
)
else -> this
}
}
else -> this
}
/* Copied from K/N */
fun IrDeclarationContainer.addChild(declaration: IrDeclaration) {
this.declarations += declaration
declaration.setDeclarationsParent(this)
}
fun <T : IrElement> T.setDeclarationsParent(parent: IrDeclarationParent): T {
accept(SetDeclarationsParentVisitor, parent)
return this
}
object SetDeclarationsParentVisitor : IrElementVisitor<Unit, IrDeclarationParent> {
override fun visitElement(element: IrElement, data: IrDeclarationParent) {
if (element !is IrDeclarationParent) {
element.acceptChildren(this, data)
}
}
override fun visitDeclaration(declaration: IrDeclarationBase, data: IrDeclarationParent) {
declaration.parent = data
super.visitDeclaration(declaration, data)
}
}
val IrFunction.isStatic: Boolean
get() = parent is IrClass && dispatchReceiverParameter == null
val IrDeclaration.isTopLevel: Boolean
get() {
if (parent is IrPackageFragment) return true
val parentClass = parent as? IrClass
return parentClass?.isFileClass == true && parentClass.parent is IrPackageFragment
}
fun IrClass.createImplicitParameterDeclarationWithWrappedDescriptor() {
thisReceiver = buildReceiverParameter(this, IrDeclarationOrigin.INSTANCE_RECEIVER, symbol.typeWithParameters(typeParameters))
}
@Suppress("UNCHECKED_CAST")
fun isElseBranch(branch: IrBranch) = branch is IrElseBranch || ((branch.condition as? IrConst<Boolean>)?.value == true)
fun IrFunction.isMethodOfAny(): Boolean =
extensionReceiverParameter == null && dispatchReceiverParameter != null &&
when (name) {
OperatorNameConventions.HASH_CODE, OperatorNameConventions.TO_STRING -> valueParameters.isEmpty()
OperatorNameConventions.EQUALS -> valueParameters.singleOrNull()?.type?.isNullableAny() == true
else -> false
}
fun IrDeclarationContainer.simpleFunctions() = declarations.flatMap {
when (it) {
is IrSimpleFunction -> listOf(it)
is IrProperty -> listOfNotNull(it.getter, it.setter)
else -> emptyList()
}
}
fun IrClass.createParameterDeclarations() {
assert(thisReceiver == null)
thisReceiver = buildReceiverParameter(this, IrDeclarationOrigin.INSTANCE_RECEIVER, symbol.typeWithParameters(typeParameters))
}
fun IrFunction.createDispatchReceiverParameter(origin: IrDeclarationOrigin? = null) {
assert(dispatchReceiverParameter == null)
dispatchReceiverParameter = factory.createValueParameter(
startOffset, endOffset,
origin ?: parentAsClass.origin,
IrValueParameterSymbolImpl(),
SpecialNames.THIS,
-1,
parentAsClass.defaultType,
null,
isCrossinline = false,
isNoinline = false,
isHidden = false,
isAssignable = false
).apply {
parent = this@createDispatchReceiverParameter
}
}
val IrFunction.allParameters: List<IrValueParameter>
get() = if (this is IrConstructor) {
ArrayList<IrValueParameter>(allParametersCount).also {
it.add(
this.constructedClass.thisReceiver
?: error(this.render())
)
addExplicitParametersTo(it)
}
} else {
explicitParameters
}
val IrFunction.allParametersCount: Int
get() = if (this is IrConstructor) explicitParametersCount + 1 else explicitParametersCount
// This is essentially the same as FakeOverrideBuilder,
// but it bypasses SymbolTable.
// TODO: merge it with FakeOverrideBuilder.
private class FakeOverrideBuilderForLowerings : FakeOverrideBuilderStrategy(emptyMap()) {
override fun linkFunctionFakeOverride(declaration: IrFakeOverrideFunction, compatibilityMode: Boolean) {
declaration.acquireSymbol(IrSimpleFunctionSymbolImpl())
}
override fun linkPropertyFakeOverride(declaration: IrFakeOverrideProperty, compatibilityMode: Boolean) {
val propertySymbol = IrPropertySymbolImpl()
declaration.getter?.let { it.correspondingPropertySymbol = propertySymbol }
declaration.setter?.let { it.correspondingPropertySymbol = propertySymbol }
declaration.acquireSymbol(propertySymbol)
declaration.getter?.let {
it.correspondingPropertySymbol = declaration.symbol
linkFunctionFakeOverride(it as? IrFakeOverrideFunction ?: error("Unexpected fake override getter: $it"), compatibilityMode)
}
declaration.setter?.let {
it.correspondingPropertySymbol = declaration.symbol
linkFunctionFakeOverride(it as? IrFakeOverrideFunction ?: error("Unexpected fake override setter: $it"), compatibilityMode)
}
}
}
fun IrClass.addFakeOverrides(typeSystem: IrTypeSystemContext, implementedMembers: List<IrOverridableMember> = emptyList()) {
IrOverridingUtil(typeSystem, FakeOverrideBuilderForLowerings())
.buildFakeOverridesForClassUsingOverriddenSymbols(this, implementedMembers, compatibilityMode = false)
.forEach { addChild(it) }
}
fun IrFactory.createStaticFunctionWithReceivers(
irParent: IrDeclarationParent,
name: Name,
oldFunction: IrFunction,
dispatchReceiverType: IrType? = oldFunction.dispatchReceiverParameter?.type,
origin: IrDeclarationOrigin = oldFunction.origin,
modality: Modality = Modality.FINAL,
visibility: DescriptorVisibility = oldFunction.visibility,
isFakeOverride: Boolean = oldFunction.isFakeOverride,
copyMetadata: Boolean = true,
typeParametersFromContext: List<IrTypeParameter> = listOf()
): IrSimpleFunction {
return createFunction(
oldFunction.startOffset, oldFunction.endOffset,
origin,
IrSimpleFunctionSymbolImpl(),
name,
visibility,
modality,
oldFunction.returnType,
isInline = oldFunction.isInline,
isExternal = false,
isTailrec = false,
isSuspend = oldFunction.isSuspend,
isExpect = oldFunction.isExpect,
isFakeOverride = isFakeOverride,
isOperator = oldFunction is IrSimpleFunction && oldFunction.isOperator,
isInfix = oldFunction is IrSimpleFunction && oldFunction.isInfix,
containerSource = oldFunction.containerSource,
).apply {
parent = irParent
val newTypeParametersFromContext = copyAndRenameConflictingTypeParametersFrom(
typeParametersFromContext,
oldFunction.typeParameters
)
val newTypeParametersFromFunction = copyTypeParametersFrom(oldFunction)
val typeParameterMap =
(typeParametersFromContext + oldFunction.typeParameters)
.zip(newTypeParametersFromContext + newTypeParametersFromFunction).toMap()
fun remap(type: IrType): IrType =
type.remapTypeParameters(oldFunction, this, typeParameterMap)
typeParameters.forEach { it.superTypes = it.superTypes.map(::remap) }
annotations = oldFunction.annotations
var offset = 0
val dispatchReceiver = oldFunction.dispatchReceiverParameter?.copyTo(
this,
name = Name.identifier("\$this"),
index = offset++,
type = remap(dispatchReceiverType!!),
origin = IrDeclarationOrigin.MOVED_DISPATCH_RECEIVER
)
val extensionReceiver = oldFunction.extensionReceiverParameter?.copyTo(
this,
name = Name.identifier("\$receiver"),
index = offset++,
origin = IrDeclarationOrigin.MOVED_EXTENSION_RECEIVER,
remapTypeMap = typeParameterMap
)
valueParameters = listOfNotNull(dispatchReceiver, extensionReceiver) +
oldFunction.valueParameters.map {
it.copyTo(
this,
index = it.index + offset,
remapTypeMap = typeParameterMap
)
}
if (copyMetadata) metadata = oldFunction.metadata
copyAttributes(oldFunction as? IrAttributeContainer)
}
}
/**
* Appends the parameters in [contextParameters] to the type parameters of
* [this] function, renaming those that may clash with a provided collection of
* [existingParameters] (e.g. type parameters of the function itself, when
* creating DefaultImpls).
*
* @returns List of newly created, possibly renamed, copies of type parameters
* in order of the corresponding parameters in [context].
*/
private fun IrSimpleFunction.copyAndRenameConflictingTypeParametersFrom(
contextParameters: List<IrTypeParameter>,
existingParameters: Collection<IrTypeParameter>
): List<IrTypeParameter> {
val newParameters = mutableListOf<IrTypeParameter>()
val existingNames =
(contextParameters.map { it.name.asString() } + existingParameters.map { it.name.asString() }).toMutableSet()
contextParameters.forEach { contextType ->
val newName = if (existingParameters.any { it.name.asString() == contextType.name.asString() }) {
val newNamePrefix = contextType.name.asString() + "_I"
val newName = newNamePrefix + generateSequence(1) { x -> x + 1 }.first { n ->
(newNamePrefix + n) !in existingNames
}
existingNames.add(newName)
newName
} else {
contextType.name.asString()
}
newParameters.add(buildTypeParameter(this) {
updateFrom(contextType)
name = Name.identifier(newName)
})
}
val zipped = contextParameters.zip(newParameters)
val parameterMap = zipped.toMap()
for ((oldParameter, newParameter) in zipped) {
newParameter.copySuperTypesFrom(oldParameter, parameterMap)
}
typeParameters = typeParameters + newParameters
return newParameters
}
val IrSymbol.isSuspend: Boolean
get() = this is IrSimpleFunctionSymbol && owner.isSuspend
fun IrSimpleFunction.allOverridden(includeSelf: Boolean = false): List<IrSimpleFunction> {
val result = mutableListOf<IrSimpleFunction>()
if (includeSelf) {
result.add(this)
}
var current = this
while (true) {
val overridden = current.overriddenSymbols
when (overridden.size) {
0 -> return result
1 -> {
current = overridden[0].owner
result.add(current)
}
else -> {
val resultSet = result.toMutableSet()
computeAllOverridden(current, resultSet)
return resultSet.toList()
}
}
}
}
private fun computeAllOverridden(function: IrSimpleFunction, result: MutableSet<IrSimpleFunction>) {
for (overriddenSymbol in function.overriddenSymbols) {
val override = overriddenSymbol.owner
if (result.add(override)) {
computeAllOverridden(override, result)
}
}
}
fun IrBuiltIns.getKFunctionType(returnType: IrType, parameterTypes: List<IrType>) =
kFunctionN(parameterTypes.size).typeWith(parameterTypes + returnType)