IR: do not use SymbolRemapper in FakeOverrideCopier

It was only used to keep track of mappings from old type/value
parameters to new. We can do it manually instead of inheriting from
DeepCopySymbolRemapper, because the latter does more work than needed,
namely it creates 16 hash maps, and traverses the IR tree looking for
any other declarations.

 #KT-66281
This commit is contained in:
Alexander Udalov
2024-03-05 17:28:30 +01:00
committed by Space Team
parent 79a224cc0f
commit df9d59851d
2 changed files with 38 additions and 60 deletions
@@ -6,38 +6,38 @@
package org.jetbrains.kotlin.ir.overrides
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
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
import org.jetbrains.kotlin.ir.util.TypeRemapper
import org.jetbrains.kotlin.ir.util.copyAnnotations
import org.jetbrains.kotlin.ir.util.findAnnotation
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.EnhancedNullability
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.FlexibleNullability
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.memoryOptimizedMap
// This is basically modelled after the inliner copier.
class CopyIrTreeWithSymbolsForFakeOverrides(
private val overridableMember: IrOverridableMember,
typeArguments: Map<IrTypeParameterSymbol, IrType>,
parentClass: IrClass,
unimplementedOverridesStrategy: IrUnimplementedOverridesStrategy
private val substitution: Map<IrTypeParameterSymbol, IrType>,
private val parentClass: IrClass,
private val unimplementedOverridesStrategy: IrUnimplementedOverridesStrategy
) {
private val symbolRemapper = FakeOverrideSymbolRemapperImpl(typeArguments, NullDescriptorsRemapper)
private val copier = FakeOverrideCopier(
symbolRemapper,
FakeOverrideTypeRemapper(symbolRemapper, typeArguments),
parentClass,
unimplementedOverridesStrategy
)
fun copy(): IrOverridableMember {
overridableMember.acceptVoid(symbolRemapper)
val typeParameters = HashMap<IrTypeParameterSymbol, IrTypeParameterSymbol>()
val valueParameters = HashMap<IrValueParameterSymbol, IrValueParameterSymbol>()
val copier = FakeOverrideCopier(
valueParameters,
typeParameters,
FakeOverrideTypeRemapper(typeParameters, substitution),
parentClass,
unimplementedOverridesStrategy
)
return when (overridableMember) {
is IrSimpleFunction -> copier.copySimpleFunction(overridableMember)
@@ -46,11 +46,10 @@ class CopyIrTreeWithSymbolsForFakeOverrides(
}
}
private inner class FakeOverrideTypeRemapper(
val symbolRemapper: SymbolRemapper,
val typeArguments: Map<IrTypeParameterSymbol, IrType>
private class FakeOverrideTypeRemapper(
val typeParameters: Map<IrTypeParameterSymbol, IrTypeParameterSymbol>,
val substitution: Map<IrTypeParameterSymbol, IrType>
) : TypeRemapper {
override fun enterScope(irTypeParametersContainer: IrTypeParametersContainer) {}
override fun leaveScope() {}
@@ -79,50 +78,23 @@ class CopyIrTreeWithSymbolsForFakeOverrides(
override fun remapType(type: IrType): IrType {
if (type !is IrSimpleType) return type
return when (val substitutedType = typeArguments[type.classifier]) {
return when (val substitutedType = substitution[type.classifier]) {
is IrDynamicType -> substitutedType
is IrSimpleType -> substitutedType.mergeNullability(type).mergeTypeAnnotations(type)
else -> type.buildSimpleType {
kotlinType = null
classifier = symbolRemapper.getReferencedClassifier(type.classifier)
classifier = remapClassifier(type.classifier)
arguments = remapTypeArguments(type.arguments)
annotations = type.copyAnnotations()
}
}
}
}
private class FakeOverrideSymbolRemapperImpl(
private val typeArguments: Map<IrTypeParameterSymbol, IrType>,
descriptorsRemapper: DescriptorsRemapper
) : DeepCopySymbolRemapper(descriptorsRemapper) {
// We need to avoid visiting parts of the tree that would not be visited by [FakeOverrideCopier]
// Otherwise, we can record symbols inside them for rebinding, but would not actually copy them.
// Normally, this is not important, as these local symbols would not be used anyway
// But they can be used in return values of functions/accessors if it is effectively a private declaration,
// e.g. public declaration inside a private class.
override fun visitField(declaration: IrField) {} // don't visit property backing field
override fun visitBlockBody(body: IrBlockBody) {} // don't visit function body and parameter default values
override fun visitExpressionBody(body: IrExpressionBody) {} // don't visit function body and parameter default values
override fun visitSimpleFunction(declaration: IrSimpleFunction, data: Nothing?) {
// In case of FIR tests with JVM IR serialization enabled, even accessing the function body with `IrFunction.body` does not work
// in some cases because it tries to load IR and ends up with unbound symbols for some reason (most likely related to KT-63509).
// So we avoid accessing the body by copying the `IrFunction.acceptChildren` implementation and removing the `body.accept` call.
declaration.typeParameters.forEach { it.accept(this, data) }
declaration.dispatchReceiverParameter?.accept(this, data)
declaration.extensionReceiverParameter?.accept(this, data)
declaration.valueParameters.forEach { it.accept(this, data) }
}
override fun getReferencedClassifier(symbol: IrClassifierSymbol): IrClassifierSymbol {
val result = super.getReferencedClassifier(symbol)
if (result !is IrTypeParameterSymbol)
return result
return typeArguments[result]?.classifierOrNull ?: result
}
private fun remapClassifier(classifier: IrClassifierSymbol): IrClassifierSymbol =
if (classifier is IrTypeParameterSymbol)
typeParameters.getOrElse(classifier) { classifier }
else
classifier
}
private companion object {
@@ -6,12 +6,16 @@
package org.jetbrains.kotlin.ir.overrides
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.util.SymbolRemapper
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.util.TypeRemapper
import org.jetbrains.kotlin.ir.util.copyAnnotations
internal class FakeOverrideCopier(
private val symbolRemapper: SymbolRemapper,
private val valueParameters: MutableMap<IrValueParameterSymbol, IrValueParameterSymbol>,
private val typeParameters: MutableMap<IrTypeParameterSymbol, IrTypeParameterSymbol>,
private val typeRemapper: TypeRemapper,
private val parentClass: IrClass,
private val unimplementedOverridesStrategy: IrUnimplementedOverridesStrategy
@@ -81,13 +85,14 @@ internal class FakeOverrideCopier(
name = declaration.name,
type = typeRemapper.remapType(declaration.type),
isAssignable = declaration.isAssignable,
symbol = symbolRemapper.getDeclaredValueParameter(declaration.symbol),
symbol = IrValueParameterSymbolImpl(null),
index = declaration.index,
varargElementType = declaration.varargElementType?.let(typeRemapper::remapType),
isCrossinline = declaration.isCrossinline,
isNoinline = declaration.isNoinline,
isHidden = declaration.isHidden,
).apply {
valueParameters[declaration.symbol] = symbol
parent = newParent
annotations = declaration.copyAnnotations()
// Don't set the default value for fake overrides.
@@ -99,11 +104,12 @@ internal class FakeOverrideCopier(
endOffset = declaration.endOffset,
origin = declaration.origin,
name = declaration.name,
symbol = symbolRemapper.getDeclaredTypeParameter(declaration.symbol),
symbol = IrTypeParameterSymbolImpl(null),
variance = declaration.variance,
index = declaration.index,
isReified = declaration.isReified,
).apply {
typeParameters[declaration.symbol] = symbol
parent = newParent
annotations = declaration.copyAnnotations()
}