diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/DeepCopyIrTreeWithDescriptors.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/DeepCopyIrTreeWithDescriptors.kt index 364334568a1..7bb40a70ccf 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/DeepCopyIrTreeWithDescriptors.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/DeepCopyIrTreeWithDescriptors.kt @@ -21,7 +21,6 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.name.Name internal class DeepCopyIrTreeWithSymbolsForInliner( - val context: CommonBackendContext, val typeArguments: Map?, val parent: IrDeclarationParent? ) { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt index b90b2e2d4b2..62cf5bc3b7e 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt @@ -120,7 +120,7 @@ class FunctionInlining( (0 until callSite.typeArgumentsCount).map { typeParameters[it].symbol to callSite.getTypeArgument(it) }.associate { it } - DeepCopyIrTreeWithSymbolsForInliner(context, typeArguments, parent) + DeepCopyIrTreeWithSymbolsForInliner(typeArguments, parent) } val substituteMap = mutableMapOf() diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt index bfac442d7b9..029ed35698c 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt @@ -62,22 +62,22 @@ open class DeepCopyIrTreeWithSymbols( } } - private fun mapDeclarationOrigin(origin: IrDeclarationOrigin) = origin - private fun mapStatementOrigin(origin: IrStatementOrigin?) = origin + protected fun mapDeclarationOrigin(origin: IrDeclarationOrigin) = origin + protected fun mapStatementOrigin(origin: IrStatementOrigin?) = origin - private inline fun T.transform() = + protected inline fun T.transform() = transform(this@DeepCopyIrTreeWithSymbols, null) as T - private inline fun List.transform() = + protected inline fun List.transform() = map { it.transform() } - private inline fun List.transformTo(destination: MutableList) = + protected inline fun List.transformTo(destination: MutableList) = mapTo(destination) { it.transform() } - private fun T.transformDeclarationsTo(destination: T) = + protected fun T.transformDeclarationsTo(destination: T) = declarations.transformTo(destination.declarations) - private fun IrType.remapType() = typeRemapper.remapType(this) + protected fun IrType.remapType() = typeRemapper.remapType(this) override fun visitElement(element: IrElement): IrElement = throw IllegalArgumentException("Unsupported element type: $element") @@ -201,7 +201,7 @@ open class DeepCopyIrTreeWithSymbols( } } - private fun IrMutableAnnotationContainer.transformAnnotations(declaration: IrAnnotationContainer) { + protected fun IrMutableAnnotationContainer.transformAnnotations(declaration: IrAnnotationContainer) { annotations = declaration.annotations.transform() } @@ -322,7 +322,7 @@ open class DeepCopyIrTreeWithSymbols( transformAnnotations(declaration) } - private fun IrTypeParametersContainer.copyTypeParametersFrom(other: IrTypeParametersContainer) { + protected fun IrTypeParametersContainer.copyTypeParametersFrom(other: IrTypeParametersContainer) { this.typeParameters = other.typeParameters.map { copyTypeParameter(it) } diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/DeepCopyIrTreeWithSymbolsForFakeOverrides.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/DeepCopyIrTreeWithSymbolsForFakeOverrides.kt new file mode 100644 index 00000000000..c8632396eea --- /dev/null +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/DeepCopyIrTreeWithSymbolsForFakeOverrides.kt @@ -0,0 +1,104 @@ +package org.jetbrains.kotlin.backend.common.serialization + +import org.jetbrains.kotlin.backend.common.DescriptorsToIrRemapper +import org.jetbrains.kotlin.backend.common.WrappedDescriptorPatcher +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer +import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +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.buildSimpleType +import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.acceptVoid + +// This is basicly modelled after the inliner copier. +class DeepCopyIrTreeWithSymbolsForFakeOverrides( + val typeArguments: Map, + val superType: IrType, + val parent: IrClass +) { + + fun copy(irElement: IrElement): IrElement { + // Create new symbols. + irElement.acceptVoid(symbolRemapper) + + // Make symbol remapper aware of the callsite's type arguments. + symbolRemapper.typeArguments = typeArguments + + // Copy IR. + val result = irElement.transform(copier, data = null) + + // Bind newly created IR with wrapped descriptors. + result.acceptVoid(WrappedDescriptorPatcher) + + result.patchDeclarationParents(parent) + return result + } + + private inner class FakeOverrideTypeRemapper( + val symbolRemapper: SymbolRemapper, + val typeArguments: Map + ) : TypeRemapper { + + override fun enterScope(irTypeParametersContainer: IrTypeParametersContainer) {} + + override fun leaveScope() {} + + private fun remapTypeArguments(arguments: List) = + arguments.map { argument -> + (argument as? IrTypeProjection)?.let { makeTypeProjection(remapType(it.type), it.variance) } + ?: argument + } + + override fun remapType(type: IrType): IrType { + if (type !is IrSimpleType) return type + + val substitutedType = typeArguments[type.classifier] + + if (substitutedType is IrDynamicType) return substitutedType + + if (substitutedType is IrSimpleType) { + return substitutedType.buildSimpleType { + kotlinType = null + hasQuestionMark = type.hasQuestionMark or substitutedType.isMarkedNullable() + } + } + + return type.buildSimpleType { + kotlinType = null + classifier = symbolRemapper.getReferencedClassifier(type.classifier) + arguments = remapTypeArguments(type.arguments) + annotations = type.annotations.map { it.transform(copier, null) as IrConstructorCall } + } + } + } + + private class FakeOverrideSymbolRemapperImpl(descriptorsRemapper: DescriptorsRemapper) : + DeepCopySymbolRemapper(descriptorsRemapper) { + + var typeArguments = mapOf() + set(value) { + field = value.asSequence().associate { + (getReferencedClassifier(it.key) as IrTypeParameterSymbol) to it.value + } + } + + override fun getReferencedClassifier(symbol: IrClassifierSymbol): IrClassifierSymbol { + val result = super.getReferencedClassifier(symbol) + if (result !is IrTypeParameterSymbol) + return result + return typeArguments[result]?.classifierOrNull ?: result + } + } + + private val symbolRemapper = FakeOverrideSymbolRemapperImpl(DescriptorsToIrRemapper) + private val copier = + FakeOverrideCopier( + symbolRemapper, + FakeOverrideTypeRemapper(symbolRemapper, typeArguments), + SymbolRenamer.DEFAULT + ) +} diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/FakeOverrideCopier.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/FakeOverrideCopier.kt new file mode 100644 index 00000000000..94e4848b1a1 --- /dev/null +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/FakeOverrideCopier.kt @@ -0,0 +1,86 @@ +package org.jetbrains.kotlin.backend.common.serialization + +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrProperty +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.declarations.impl.IrFakeOverrideFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFakeOverridePropertyImpl +import org.jetbrains.kotlin.ir.util.* + +class FakeOverrideCopier( + symbolRemapper: SymbolRemapper, + private val typeRemapper: TypeRemapper, + private val symbolRenamer: SymbolRenamer +) : DeepCopyIrTreeWithSymbols(symbolRemapper, typeRemapper, symbolRenamer) { + + private fun T.transformFunctionChildren(declaration: T): T = + apply { + transformAnnotations(declaration) + copyTypeParametersFrom(declaration) + typeRemapper.withinScope(this) { + // This is the more correct way to produce dispatch receiver for a fake override, + // but some lowerings still expect the below behavior as produced by the current psi2ir. + /* + val superDispatchReceiver = declaration.dispatchReceiverParameter!! + val dispatchReceiverSymbol = IrValueParameterSymbolImpl(WrappedReceiverParameterDescriptor()) + val dispatchReceiverType = destinationClass.defaultType + dispatchReceiverParameter = IrValueParameterImpl( + superDispatchReceiver.startOffset, + superDispatchReceiver.endOffset, + superDispatchReceiver.origin, + dispatchReceiverSymbol, + superDispatchReceiver.name, + superDispatchReceiver.index, + dispatchReceiverType, + null, + superDispatchReceiver.isCrossinline, + superDispatchReceiver.isNoinline + ) + */ + // Should fake override's receiver be the current class is an open question. + dispatchReceiverParameter = declaration.dispatchReceiverParameter?.transform() + extensionReceiverParameter = declaration.extensionReceiverParameter?.transform() + returnType = typeRemapper.remapType(declaration.returnType) + this.valueParameters = declaration.valueParameters.transform() + } + } + + override fun visitSimpleFunction(declaration: IrSimpleFunction): IrSimpleFunction = + IrFakeOverrideFunctionImpl( + declaration.startOffset, declaration.endOffset, + IrDeclarationOrigin.FAKE_OVERRIDE, + symbolRenamer.getFunctionName(declaration.symbol), + declaration.visibility, + declaration.modality, + declaration.returnType, + isInline = declaration.isInline, + isExternal = false, + isTailrec = declaration.isTailrec, + isSuspend = declaration.isSuspend, + isExpect = declaration.isExpect, + isOperator = declaration.isOperator + ).apply { + transformFunctionChildren(declaration) + } + + + override fun visitProperty(declaration: IrProperty): IrProperty = + IrFakeOverridePropertyImpl( + declaration.startOffset, declaration.endOffset, + IrDeclarationOrigin.FAKE_OVERRIDE, + declaration.name, + declaration.visibility, + declaration.modality, + isVar = declaration.isVar, + isConst = declaration.isConst, + isLateinit = declaration.isLateinit, + isDelegated = declaration.isDelegated, + isExpect = declaration.isExpect, + isExternal = false + ).apply { + transformAnnotations(declaration) + this.getter = declaration.getter?.transform() + this.setter = declaration.setter?.transform() + } +}