[IR] Extract ActualizerSymbolRemapper and ActualizerVisitor from ExpectActualLinker

It will provide the possibility to use them not only locally

Clarify code of IrActualizer pipeline
This commit is contained in:
Ivan Kochurkin
2023-03-31 22:47:11 +02:00
committed by Space Team
parent 2ccad553e6
commit 1073797ed3
7 changed files with 162 additions and 178 deletions
@@ -5,157 +5,148 @@
package org.jetbrains.kotlin.backend.common.actualizer
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols
import org.jetbrains.kotlin.ir.util.DeepCopyTypeRemapper
import org.jetbrains.kotlin.ir.util.SymbolRemapper
import org.jetbrains.kotlin.ir.util.SymbolRenamer
import org.jetbrains.kotlin.ir.util.*
class ExpectActualLinker(private val expectActualMap: Map<IrSymbol, IrSymbol>) {
private val symbolRemapper = object : SymbolRemapper {
override fun getDeclaredClass(symbol: IrClassSymbol) = symbol
internal class ActualizerSymbolRemapper(private val expectActualMap: Map<IrSymbol, IrSymbol>) : SymbolRemapper {
override fun getDeclaredClass(symbol: IrClassSymbol) = symbol
override fun getDeclaredScript(symbol: IrScriptSymbol) = symbol
override fun getDeclaredScript(symbol: IrScriptSymbol) = symbol
override fun getDeclaredFunction(symbol: IrSimpleFunctionSymbol) = symbol
override fun getDeclaredFunction(symbol: IrSimpleFunctionSymbol) = symbol
override fun getDeclaredProperty(symbol: IrPropertySymbol) = symbol
override fun getDeclaredProperty(symbol: IrPropertySymbol) = symbol
override fun getDeclaredField(symbol: IrFieldSymbol) = symbol
override fun getDeclaredField(symbol: IrFieldSymbol) = symbol
override fun getDeclaredFile(symbol: IrFileSymbol) = symbol
override fun getDeclaredFile(symbol: IrFileSymbol) = symbol
override fun getDeclaredConstructor(symbol: IrConstructorSymbol) = symbol
override fun getDeclaredConstructor(symbol: IrConstructorSymbol) = symbol
override fun getDeclaredEnumEntry(symbol: IrEnumEntrySymbol) = symbol
override fun getDeclaredEnumEntry(symbol: IrEnumEntrySymbol) = symbol
override fun getDeclaredExternalPackageFragment(symbol: IrExternalPackageFragmentSymbol) = symbol
override fun getDeclaredExternalPackageFragment(symbol: IrExternalPackageFragmentSymbol) = symbol
override fun getDeclaredVariable(symbol: IrVariableSymbol) = symbol
override fun getDeclaredVariable(symbol: IrVariableSymbol) = symbol
override fun getDeclaredLocalDelegatedProperty(symbol: IrLocalDelegatedPropertySymbol) = symbol
override fun getDeclaredLocalDelegatedProperty(symbol: IrLocalDelegatedPropertySymbol) = symbol
override fun getDeclaredTypeParameter(symbol: IrTypeParameterSymbol) = symbol
override fun getDeclaredTypeParameter(symbol: IrTypeParameterSymbol) = symbol
override fun getDeclaredValueParameter(symbol: IrValueParameterSymbol) = symbol
override fun getDeclaredValueParameter(symbol: IrValueParameterSymbol) = symbol
override fun getDeclaredTypeAlias(symbol: IrTypeAliasSymbol) = symbol
override fun getDeclaredTypeAlias(symbol: IrTypeAliasSymbol) = symbol
override fun getReferencedClass(symbol: IrClassSymbol) = symbol.actualizeSymbol()
override fun getReferencedClass(symbol: IrClassSymbol) = symbol.actualizeSymbol()
override fun getReferencedScript(symbol: IrScriptSymbol) = symbol.actualizeSymbol()
override fun getReferencedScript(symbol: IrScriptSymbol) = symbol.actualizeSymbol()
override fun getReferencedClassOrNull(symbol: IrClassSymbol?) = symbol?.actualizeSymbol()
override fun getReferencedClassOrNull(symbol: IrClassSymbol?) = symbol?.actualizeSymbol()
override fun getReferencedEnumEntry(symbol: IrEnumEntrySymbol) = symbol.actualizeSymbol()
override fun getReferencedEnumEntry(symbol: IrEnumEntrySymbol) = symbol.actualizeSymbol()
override fun getReferencedVariable(symbol: IrVariableSymbol) = symbol.actualizeSymbol()
override fun getReferencedVariable(symbol: IrVariableSymbol) = symbol.actualizeSymbol()
override fun getReferencedLocalDelegatedProperty(symbol: IrLocalDelegatedPropertySymbol) = symbol.actualizeSymbol()
override fun getReferencedLocalDelegatedProperty(symbol: IrLocalDelegatedPropertySymbol) = symbol.actualizeSymbol()
override fun getReferencedField(symbol: IrFieldSymbol) = symbol.actualizeSymbol()
override fun getReferencedField(symbol: IrFieldSymbol) = symbol.actualizeSymbol()
override fun getReferencedConstructor(symbol: IrConstructorSymbol) = symbol.actualizeSymbol()
override fun getReferencedConstructor(symbol: IrConstructorSymbol) = symbol.actualizeSymbol()
override fun getReferencedValue(symbol: IrValueSymbol) = symbol.actualizeSymbol()
override fun getReferencedValue(symbol: IrValueSymbol) = symbol.actualizeSymbol()
override fun getReferencedFunction(symbol: IrFunctionSymbol) = symbol.actualizeSymbol()
override fun getReferencedFunction(symbol: IrFunctionSymbol) = symbol.actualizeSymbol()
override fun getReferencedProperty(symbol: IrPropertySymbol) = symbol.actualizeSymbol()
override fun getReferencedProperty(symbol: IrPropertySymbol) = symbol.actualizeSymbol()
override fun getReferencedSimpleFunction(symbol: IrSimpleFunctionSymbol) = symbol.actualizeSymbol()
override fun getReferencedSimpleFunction(symbol: IrSimpleFunctionSymbol) = symbol.actualizeSymbol()
override fun getReferencedReturnableBlock(symbol: IrReturnableBlockSymbol) = symbol.actualizeSymbol()
override fun getReferencedReturnableBlock(symbol: IrReturnableBlockSymbol) = symbol.actualizeSymbol()
override fun getReferencedClassifier(symbol: IrClassifierSymbol) = symbol.actualizeSymbol()
override fun getReferencedClassifier(symbol: IrClassifierSymbol) = symbol.actualizeSymbol()
override fun getReferencedTypeAlias(symbol: IrTypeAliasSymbol) = symbol.actualizeSymbol()
override fun getReferencedTypeAlias(symbol: IrTypeAliasSymbol) = symbol.actualizeSymbol()
private inline fun <reified S : IrSymbol> S.actualizeSymbol(): S = (expectActualMap[this] as? S) ?: this
}
private inline fun <reified S : IrSymbol> S.actualizeSymbol(): S = (expectActualMap[this] as? S) ?: this
}
private val typeRemapper = DeepCopyTypeRemapper(symbolRemapper)
internal open class ActualizerVisitor(symbolRemapper: SymbolRemapper, typeRemapper: TypeRemapper) :
DeepCopyIrTreeWithSymbols(symbolRemapper, typeRemapper, SymbolRenamer.DEFAULT) {
override fun visitModuleFragment(declaration: IrModuleFragment) =
declaration.also { it.transformChildren(this, null) }
private val actualizer = object : DeepCopyIrTreeWithSymbols(symbolRemapper, typeRemapper, SymbolRenamer.DEFAULT) {
override fun visitModuleFragment(declaration: IrModuleFragment) =
declaration.also { it.transformChildren(this, null) }
override fun visitExternalPackageFragment(declaration: IrExternalPackageFragment) =
declaration.also { it.transformChildren(this, null) }
override fun visitExternalPackageFragment(declaration: IrExternalPackageFragment) =
declaration.also { it.transformChildren(this, null) }
override fun visitFile(declaration: IrFile) =
declaration.also { it.transformChildren(this, null) }
override fun visitFile(declaration: IrFile) =
declaration.also { it.transformChildren(this, null) }
override fun visitScript(declaration: IrScript) =
declaration.also {
it.baseClass = it.baseClass?.remapType()
it.transformChildren(this, null)
}
override fun visitScript(declaration: IrScript) =
declaration.also {
it.baseClass = it.baseClass?.remapType()
it.transformChildren(this, null)
}
override fun visitClass(declaration: IrClass) =
declaration.also {
it.superTypes = it.superTypes.map { superType -> superType.remapType() }
it.transformChildren(this, null)
}
override fun visitClass(declaration: IrClass) =
declaration.also {
it.superTypes = it.superTypes.map { superType -> superType.remapType() }
it.transformChildren(this, null)
}
override fun visitSimpleFunction(declaration: IrSimpleFunction) = visitFunction(declaration) as IrSimpleFunction
override fun visitSimpleFunction(declaration: IrSimpleFunction) = visitFunction(declaration) as IrSimpleFunction
override fun visitConstructor(declaration: IrConstructor) = visitFunction(declaration) as IrConstructor
override fun visitConstructor(declaration: IrConstructor) = visitFunction(declaration) as IrConstructor
override fun visitFunction(declaration: IrFunction) =
declaration.also {
it.returnType = it.returnType.remapType()
it.transformChildren(this, null)
}
override fun visitFunction(declaration: IrFunction) =
declaration.also {
it.returnType = it.returnType.remapType()
it.transformChildren(this, null)
}
override fun visitProperty(declaration: IrProperty) =
declaration.also { it.transformChildren(this, null) }
override fun visitProperty(declaration: IrProperty) =
declaration.also { it.transformChildren(this, null) }
override fun visitField(declaration: IrField) =
declaration.also {
it.type = it.type.remapType()
it.transformChildren(this, null)
}
override fun visitField(declaration: IrField) =
declaration.also {
it.type = it.type.remapType()
it.transformChildren(this, null)
}
override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty) =
declaration.also {
it.type = it.type.remapType()
it.transformChildren(this, null)
}
override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty) =
declaration.also {
it.type = it.type.remapType()
it.transformChildren(this, null)
}
override fun visitEnumEntry(declaration: IrEnumEntry) =
declaration.also { it.transformChildren(this, null) }
override fun visitEnumEntry(declaration: IrEnumEntry) =
declaration.also { it.transformChildren(this, null) }
override fun visitTypeParameter(declaration: IrTypeParameter) =
declaration.also {
it.superTypes = it.superTypes.map { superType -> superType.remapType() }
it.transformChildren(this, null)
}
override fun visitTypeParameter(declaration: IrTypeParameter) =
declaration.also {
it.superTypes = it.superTypes.map { superType -> superType.remapType() }
it.transformChildren(this, null)
}
override fun visitValueParameter(declaration: IrValueParameter) =
declaration.also {
it.type = it.type.remapType()
it.varargElementType = it.varargElementType?.remapType()
it.transformChildren(this, null)
}
override fun visitValueParameter(declaration: IrValueParameter) =
declaration.also {
it.type = it.type.remapType()
it.varargElementType = it.varargElementType?.remapType()
it.transformChildren(this, null)
}
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer) =
declaration.also { it.transformChildren(this, null) }
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer) =
declaration.also { it.transformChildren(this, null) }
override fun visitVariable(declaration: IrVariable) =
declaration.also {
it.type = it.type.remapType()
it.transformChildren(this, null)
}
override fun visitVariable(declaration: IrVariable) =
declaration.also {
it.type = it.type.remapType()
it.transformChildren(this, null)
}
override fun visitTypeAlias(declaration: IrTypeAlias) =
declaration.also {
it.expandedType = it.expandedType.remapType()
it.transformChildren(this, null)
}
}
fun actualize(irElement: IrElement) = irElement.transform(actualizer, null)
override fun visitTypeAlias(declaration: IrTypeAlias) =
declaration.also {
it.expandedType = it.expandedType.remapType()
it.transformChildren(this, null)
}
}
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
class FunctionDefaultParametersActualizer(private val expectActualMap: Map<IrSymbol, IrSymbol>) {
internal class FunctionDefaultParametersActualizer(private val expectActualMap: Map<IrSymbol, IrSymbol>) {
fun actualize() {
for ((expect, actual) in expectActualMap) {
if (expect is IrFunctionSymbol) {
@@ -26,7 +26,6 @@ class FunctionDefaultParametersActualizer(private val expectActualMap: Map<IrSym
if (actualParameter.defaultValue == null && expectDefaultValue != null) {
actualParameter.defaultValue = expectDefaultValue.copyAndActualizeDefaultValue(
actualFunction,
actualParameter,
mapOf(),
classActualizer = { (expectActualMap[it.symbol] as IrClassSymbol).owner },
functionActualizer = { (expectActualMap[it.symbol] as IrFunctionSymbol).owner }
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.ir.util.DeepCopyTypeRemapper
data class IrActualizationResult(val actualizedExpectDeclarations: List<IrDeclaration>)
@@ -22,22 +22,41 @@ object IrActualizer {
languageVersionSettings: LanguageVersionSettings
): IrActualizationResult {
val ktDiagnosticReporter = KtDiagnosticReporterWithImplicitIrBasedContext(diagnosticReporter, languageVersionSettings)
val (expectActualMap, expectActualTypeAliasMap) = ExpectActualCollector(mainFragment, dependentFragments, ktDiagnosticReporter).collect()
val (expectActualMap, expectActualTypeAliasMap) = ExpectActualCollector(
mainFragment,
dependentFragments,
ktDiagnosticReporter
).collect()
val removedExpectDeclarations = removeExpectDeclarations(dependentFragments, expectActualMap)
val symbolRemapper = ActualizerSymbolRemapper(expectActualMap)
val typeRemapper = DeepCopyTypeRemapper(symbolRemapper)
FunctionDefaultParametersActualizer(expectActualMap).actualize()
val removedExpectDeclarationMetadata = removeExpectDeclarations(dependentFragments, expectActualMap)
addMissingFakeOverrides(expectActualMap, dependentFragments, expectActualTypeAliasMap, ktDiagnosticReporter)
linkExpectToActual(expectActualMap, dependentFragments)
MissingFakeOverridesAdder(
expectActualMap,
expectActualTypeAliasMap,
ktDiagnosticReporter
).apply { dependentFragments.forEach { visitModuleFragment(it) } }
val actualizerVisitor = ActualizerVisitor(symbolRemapper, typeRemapper)
dependentFragments.forEach { it.transform(actualizerVisitor, null) }
mergeIrFragments(mainFragment, dependentFragments)
return IrActualizationResult(removedExpectDeclarationMetadata)
return IrActualizationResult(removedExpectDeclarations)
}
private fun removeExpectDeclarations(dependentFragments: List<IrModuleFragment>, expectActualMap: Map<IrSymbol, IrSymbol>): List<IrDeclaration> {
val removedDeclarationMetadata = mutableListOf<IrDeclaration>()
val removedExpectDeclarations = mutableListOf<IrDeclaration>()
for (fragment in dependentFragments) {
for (file in fragment.files) {
file.declarations.removeIf {
if (shouldRemoveExpectDeclaration(it, expectActualMap)) {
removedDeclarationMetadata.add(it)
removedExpectDeclarations.add(it)
true
} else {
false
@@ -45,7 +64,7 @@ object IrActualizer {
}
}
}
return removedDeclarationMetadata
return removedExpectDeclarations
}
private fun shouldRemoveExpectDeclaration(irDeclaration: IrDeclaration, expectActualMap: Map<IrSymbol, IrSymbol>): Boolean {
@@ -57,23 +76,6 @@ object IrActualizer {
}
}
private fun addMissingFakeOverrides(
expectActualMap: Map<IrSymbol, IrSymbol>,
dependentFragments: List<IrModuleFragment>,
expectActualTypeAliasMap: Map<FqName, FqName>,
diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext
) {
MissingFakeOverridesAdder(
expectActualMap,
expectActualTypeAliasMap,
diagnosticsReporter
).apply { dependentFragments.forEach { visitModuleFragment(it) } }
}
private fun linkExpectToActual(expectActualMap: Map<IrSymbol, IrSymbol>, dependentFragments: List<IrModuleFragment>) {
ExpectActualLinker(expectActualMap).apply { dependentFragments.forEach { actualize(it) } }
}
private fun mergeIrFragments(mainFragment: IrModuleFragment, dependentFragments: List<IrModuleFragment>) {
mainFragment.files.addAll(0, dependentFragments.flatMap { it.files })
}
@@ -108,9 +108,9 @@ private fun IrFunction.match(actualFunction: IrFunction, expectActualTypesMap: M
return true
}
fun generateActualIrClassOrTypeAliasFullName(declaration: IrElement) = generateIrElementFullNameFromExpect(declaration, emptyMap())
internal fun generateActualIrClassOrTypeAliasFullName(declaration: IrElement) = generateIrElementFullNameFromExpect(declaration, emptyMap())
fun generateIrElementFullNameFromExpect(
internal fun generateIrElementFullNameFromExpect(
declaration: IrElement,
expectActualTypeAliasMap: Map<FqName, FqName>
): String {
@@ -157,7 +157,7 @@ private fun appendElementFullName(
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun KtDiagnosticReporterWithImplicitIrBasedContext.reportMissingActual(irDeclaration: IrDeclaration) {
internal fun KtDiagnosticReporterWithImplicitIrBasedContext.reportMissingActual(irDeclaration: IrDeclaration) {
at(irDeclaration).report(
CommonBackendErrors.NO_ACTUAL_FOR_EXPECT,
(irDeclaration as? IrDeclarationWithName)?.name?.asString().orEmpty(),
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.name.FqName
class MissingFakeOverridesAdder(
internal class MissingFakeOverridesAdder(
private val expectActualMap: Map<IrSymbol, IrSymbol>,
private val typeAliasMap: Map<FqName, FqName>,
private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext
@@ -151,7 +151,6 @@ open class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, priva
defaultValue.let { originalDefault ->
declaration.defaultValue = originalDefault.copyAndActualizeDefaultValue(
function,
declaration,
typeParameterSubstitutionMap.getValue(expectToActual),
classActualizer = { symbolTable.referenceClass(it.descriptor.findActualForExpect() as ClassDescriptor).owner },
functionActualizer = { symbolTable.referenceFunction(it.descriptor.findActualForExpect() as FunctionDescriptor).owner }
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.linkage.partial.isPartialLinkageRuntimeError
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrFail
@@ -256,58 +255,52 @@ fun ParameterDescriptor.copyAsValueParameter(newOwner: CallableDescriptor, index
fun IrExpressionBody.copyAndActualizeDefaultValue(
actualFunction: IrFunction,
actualValueParameter: IrValueParameter,
expectActualTypeParametersMap: Map<IrTypeParameter, IrTypeParameter>,
classActualizer: (IrClass) -> IrClass,
functionActualizer: (IrFunction) -> IrFunction
) = actualValueParameter.factory.createExpressionBody(startOffset, endOffset) {
expression = this@copyAndActualizeDefaultValue.expression
): IrExpressionBody {
return this
.deepCopyWithSymbols(actualFunction) { symbolRemapper, _ ->
DeepCopyIrTreeWithSymbols(symbolRemapper, IrTypeParameterRemapper(expectActualTypeParametersMap))
}
.transform(object : IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid()
val newValue = remapExpectValue(expression.symbol) ?: return expression
return IrGetValueImpl(
expression.startOffset,
expression.endOffset,
newValue.type,
newValue.symbol,
expression.origin
return expression.actualizeForDefaultValue(
classActualizer = { classActualizer(it) },
functionActualizer = { functionActualizer(it) }
)
}
private fun remapExpectValue(symbol: IrValueSymbol): IrValueParameter? {
if (symbol !is IrValueParameterSymbol) {
return null
}
val parameter = symbol.owner
return when (val parent = parameter.parent) {
is IrClass -> {
assert(parameter == parent.thisReceiver)
classActualizer(parent).thisReceiver!!
}
is IrFunction -> {
val function = functionActualizer(parent)
when (parameter) {
parent.dispatchReceiverParameter -> function.dispatchReceiverParameter!!
parent.extensionReceiverParameter -> function.extensionReceiverParameter!!
else -> {
assert(parent.valueParameters[parameter.index] == parameter)
function.valueParameters[parameter.index]
}
}
}
else -> error(parent)
}
}
}, data = null)
}
fun IrGetValue.actualizeForDefaultValue(classActualizer: (IrClass) -> IrClass, functionActualizer: (IrFunction) -> IrFunction): IrGetValue {
val symbol = symbol
if (symbol !is IrValueParameterSymbol) {
return this
}
val parameter = symbol.owner
val newSymbol = when (val parent = parameter.parent) {
is IrClass -> {
assert(parameter == parent.thisReceiver)
classActualizer(parent).thisReceiver!!
}
is IrFunction -> {
val function = functionActualizer(parent)
when (parameter) {
parent.dispatchReceiverParameter -> function.dispatchReceiverParameter!!
parent.extensionReceiverParameter -> function.extensionReceiverParameter!!
else -> {
assert(parent.valueParameters[parameter.index] == parameter)
function.valueParameters[parameter.index]
}
}
}
else -> error(parent)
}
return IrGetValueImpl(startOffset, endOffset, newSymbol.type, newSymbol.symbol, origin)
}