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:
committed by
Space Team
parent
79a224cc0f
commit
df9d59851d
+28
-56
@@ -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()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user