Created a deep copier good for fake overrides.
Adapted it from inliner copier. It is capable of producing type substituted members.
This commit is contained in:
-1
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
internal class DeepCopyIrTreeWithSymbolsForInliner(
|
internal class DeepCopyIrTreeWithSymbolsForInliner(
|
||||||
val context: CommonBackendContext,
|
|
||||||
val typeArguments: Map<IrTypeParameterSymbol, IrType?>?,
|
val typeArguments: Map<IrTypeParameterSymbol, IrType?>?,
|
||||||
val parent: IrDeclarationParent?
|
val parent: IrDeclarationParent?
|
||||||
) {
|
) {
|
||||||
|
|||||||
+1
-1
@@ -120,7 +120,7 @@ class FunctionInlining(
|
|||||||
(0 until callSite.typeArgumentsCount).map {
|
(0 until callSite.typeArgumentsCount).map {
|
||||||
typeParameters[it].symbol to callSite.getTypeArgument(it)
|
typeParameters[it].symbol to callSite.getTypeArgument(it)
|
||||||
}.associate { it }
|
}.associate { it }
|
||||||
DeepCopyIrTreeWithSymbolsForInliner(context, typeArguments, parent)
|
DeepCopyIrTreeWithSymbolsForInliner(typeArguments, parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
val substituteMap = mutableMapOf<IrValueParameter, IrExpression>()
|
val substituteMap = mutableMapOf<IrValueParameter, IrExpression>()
|
||||||
|
|||||||
@@ -62,22 +62,22 @@ open class DeepCopyIrTreeWithSymbols(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun mapDeclarationOrigin(origin: IrDeclarationOrigin) = origin
|
protected fun mapDeclarationOrigin(origin: IrDeclarationOrigin) = origin
|
||||||
private fun mapStatementOrigin(origin: IrStatementOrigin?) = origin
|
protected fun mapStatementOrigin(origin: IrStatementOrigin?) = origin
|
||||||
|
|
||||||
private inline fun <reified T : IrElement> T.transform() =
|
protected inline fun <reified T : IrElement> T.transform() =
|
||||||
transform(this@DeepCopyIrTreeWithSymbols, null) as T
|
transform(this@DeepCopyIrTreeWithSymbols, null) as T
|
||||||
|
|
||||||
private inline fun <reified T : IrElement> List<T>.transform() =
|
protected inline fun <reified T : IrElement> List<T>.transform() =
|
||||||
map { it.transform() }
|
map { it.transform() }
|
||||||
|
|
||||||
private inline fun <reified T : IrElement> List<T>.transformTo(destination: MutableList<T>) =
|
protected inline fun <reified T : IrElement> List<T>.transformTo(destination: MutableList<T>) =
|
||||||
mapTo(destination) { it.transform() }
|
mapTo(destination) { it.transform() }
|
||||||
|
|
||||||
private fun <T : IrDeclarationContainer> T.transformDeclarationsTo(destination: T) =
|
protected fun <T : IrDeclarationContainer> T.transformDeclarationsTo(destination: T) =
|
||||||
declarations.transformTo(destination.declarations)
|
declarations.transformTo(destination.declarations)
|
||||||
|
|
||||||
private fun IrType.remapType() = typeRemapper.remapType(this)
|
protected fun IrType.remapType() = typeRemapper.remapType(this)
|
||||||
|
|
||||||
override fun visitElement(element: IrElement): IrElement =
|
override fun visitElement(element: IrElement): IrElement =
|
||||||
throw IllegalArgumentException("Unsupported element type: $element")
|
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()
|
annotations = declaration.annotations.transform()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,7 +322,7 @@ open class DeepCopyIrTreeWithSymbols(
|
|||||||
transformAnnotations(declaration)
|
transformAnnotations(declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrTypeParametersContainer.copyTypeParametersFrom(other: IrTypeParametersContainer) {
|
protected fun IrTypeParametersContainer.copyTypeParametersFrom(other: IrTypeParametersContainer) {
|
||||||
this.typeParameters = other.typeParameters.map {
|
this.typeParameters = other.typeParameters.map {
|
||||||
copyTypeParameter(it)
|
copyTypeParameter(it)
|
||||||
}
|
}
|
||||||
|
|||||||
+104
@@ -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<IrTypeParameterSymbol, IrType>,
|
||||||
|
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<IrTypeParameterSymbol, IrType>
|
||||||
|
) : TypeRemapper {
|
||||||
|
|
||||||
|
override fun enterScope(irTypeParametersContainer: IrTypeParametersContainer) {}
|
||||||
|
|
||||||
|
override fun leaveScope() {}
|
||||||
|
|
||||||
|
private fun remapTypeArguments(arguments: List<IrTypeArgument>) =
|
||||||
|
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<IrTypeParameterSymbol, IrType>()
|
||||||
|
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
|
||||||
|
)
|
||||||
|
}
|
||||||
+86
@@ -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 : IrFunction> 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user