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
|
||||
|
||||
internal class DeepCopyIrTreeWithSymbolsForInliner(
|
||||
val context: CommonBackendContext,
|
||||
val typeArguments: Map<IrTypeParameterSymbol, IrType?>?,
|
||||
val parent: IrDeclarationParent?
|
||||
) {
|
||||
|
||||
+1
-1
@@ -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<IrValueParameter, IrExpression>()
|
||||
|
||||
@@ -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 <reified T : IrElement> T.transform() =
|
||||
protected inline fun <reified T : IrElement> T.transform() =
|
||||
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() }
|
||||
|
||||
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() }
|
||||
|
||||
private fun <T : IrDeclarationContainer> T.transformDeclarationsTo(destination: T) =
|
||||
protected fun <T : IrDeclarationContainer> 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)
|
||||
}
|
||||
|
||||
+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