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 package org.jetbrains.kotlin.ir.overrides
import org.jetbrains.kotlin.ir.declarations.* 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.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol 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.*
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.TypeRemapper
import org.jetbrains.kotlin.ir.visitors.acceptVoid 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.EnhancedNullability
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.FlexibleNullability import org.jetbrains.kotlin.name.StandardClassIds.Annotations.FlexibleNullability
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.memoryOptimizedMap import org.jetbrains.kotlin.utils.memoryOptimizedMap
// This is basically modelled after the inliner copier.
class CopyIrTreeWithSymbolsForFakeOverrides( class CopyIrTreeWithSymbolsForFakeOverrides(
private val overridableMember: IrOverridableMember, private val overridableMember: IrOverridableMember,
typeArguments: Map<IrTypeParameterSymbol, IrType>, private val substitution: Map<IrTypeParameterSymbol, IrType>,
parentClass: IrClass, private val parentClass: IrClass,
unimplementedOverridesStrategy: IrUnimplementedOverridesStrategy private val unimplementedOverridesStrategy: IrUnimplementedOverridesStrategy
) { ) {
private val symbolRemapper = FakeOverrideSymbolRemapperImpl(typeArguments, NullDescriptorsRemapper)
private val copier = FakeOverrideCopier(
symbolRemapper,
FakeOverrideTypeRemapper(symbolRemapper, typeArguments),
parentClass,
unimplementedOverridesStrategy
)
fun copy(): IrOverridableMember { 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) { return when (overridableMember) {
is IrSimpleFunction -> copier.copySimpleFunction(overridableMember) is IrSimpleFunction -> copier.copySimpleFunction(overridableMember)
@@ -46,11 +46,10 @@ class CopyIrTreeWithSymbolsForFakeOverrides(
} }
} }
private inner class FakeOverrideTypeRemapper( private class FakeOverrideTypeRemapper(
val symbolRemapper: SymbolRemapper, val typeParameters: Map<IrTypeParameterSymbol, IrTypeParameterSymbol>,
val typeArguments: Map<IrTypeParameterSymbol, IrType> val substitution: Map<IrTypeParameterSymbol, IrType>
) : TypeRemapper { ) : TypeRemapper {
override fun enterScope(irTypeParametersContainer: IrTypeParametersContainer) {} override fun enterScope(irTypeParametersContainer: IrTypeParametersContainer) {}
override fun leaveScope() {} override fun leaveScope() {}
@@ -79,50 +78,23 @@ class CopyIrTreeWithSymbolsForFakeOverrides(
override fun remapType(type: IrType): IrType { override fun remapType(type: IrType): IrType {
if (type !is IrSimpleType) return type if (type !is IrSimpleType) return type
return when (val substitutedType = typeArguments[type.classifier]) { return when (val substitutedType = substitution[type.classifier]) {
is IrDynamicType -> substitutedType is IrDynamicType -> substitutedType
is IrSimpleType -> substitutedType.mergeNullability(type).mergeTypeAnnotations(type) is IrSimpleType -> substitutedType.mergeNullability(type).mergeTypeAnnotations(type)
else -> type.buildSimpleType { else -> type.buildSimpleType {
kotlinType = null kotlinType = null
classifier = symbolRemapper.getReferencedClassifier(type.classifier) classifier = remapClassifier(type.classifier)
arguments = remapTypeArguments(type.arguments) arguments = remapTypeArguments(type.arguments)
annotations = type.copyAnnotations() annotations = type.copyAnnotations()
} }
} }
} }
}
private class FakeOverrideSymbolRemapperImpl( private fun remapClassifier(classifier: IrClassifierSymbol): IrClassifierSymbol =
private val typeArguments: Map<IrTypeParameterSymbol, IrType>, if (classifier is IrTypeParameterSymbol)
descriptorsRemapper: DescriptorsRemapper typeParameters.getOrElse(classifier) { classifier }
) : DeepCopySymbolRemapper(descriptorsRemapper) { else
classifier
// 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 companion object { private companion object {
@@ -6,12 +6,16 @@
package org.jetbrains.kotlin.ir.overrides package org.jetbrains.kotlin.ir.overrides
import org.jetbrains.kotlin.ir.declarations.* 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.TypeRemapper
import org.jetbrains.kotlin.ir.util.copyAnnotations import org.jetbrains.kotlin.ir.util.copyAnnotations
internal class FakeOverrideCopier( 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 typeRemapper: TypeRemapper,
private val parentClass: IrClass, private val parentClass: IrClass,
private val unimplementedOverridesStrategy: IrUnimplementedOverridesStrategy private val unimplementedOverridesStrategy: IrUnimplementedOverridesStrategy
@@ -81,13 +85,14 @@ internal class FakeOverrideCopier(
name = declaration.name, name = declaration.name,
type = typeRemapper.remapType(declaration.type), type = typeRemapper.remapType(declaration.type),
isAssignable = declaration.isAssignable, isAssignable = declaration.isAssignable,
symbol = symbolRemapper.getDeclaredValueParameter(declaration.symbol), symbol = IrValueParameterSymbolImpl(null),
index = declaration.index, index = declaration.index,
varargElementType = declaration.varargElementType?.let(typeRemapper::remapType), varargElementType = declaration.varargElementType?.let(typeRemapper::remapType),
isCrossinline = declaration.isCrossinline, isCrossinline = declaration.isCrossinline,
isNoinline = declaration.isNoinline, isNoinline = declaration.isNoinline,
isHidden = declaration.isHidden, isHidden = declaration.isHidden,
).apply { ).apply {
valueParameters[declaration.symbol] = symbol
parent = newParent parent = newParent
annotations = declaration.copyAnnotations() annotations = declaration.copyAnnotations()
// Don't set the default value for fake overrides. // Don't set the default value for fake overrides.
@@ -99,11 +104,12 @@ internal class FakeOverrideCopier(
endOffset = declaration.endOffset, endOffset = declaration.endOffset,
origin = declaration.origin, origin = declaration.origin,
name = declaration.name, name = declaration.name,
symbol = symbolRemapper.getDeclaredTypeParameter(declaration.symbol), symbol = IrTypeParameterSymbolImpl(null),
variance = declaration.variance, variance = declaration.variance,
index = declaration.index, index = declaration.index,
isReified = declaration.isReified, isReified = declaration.isReified,
).apply { ).apply {
typeParameters[declaration.symbol] = symbol
parent = newParent parent = newParent
annotations = declaration.copyAnnotations() annotations = declaration.copyAnnotations()
} }