[IR] Partial linkage fix: Implement abstract fake overrides in non-abstract classes so that there are no call sites that still refer to abstract fake overrides

^KT-53663
This commit is contained in:
Dmitriy Dolovov
2022-08-31 12:10:00 +02:00
parent cb20998d93
commit 71d51801ce
12 changed files with 177 additions and 201 deletions
@@ -5,8 +5,8 @@
package org.jetbrains.kotlin.ir.overrides
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrOverridableMember
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
@@ -17,18 +17,26 @@ 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(typeArguments: Map<IrTypeParameterSymbol, IrType>) {
fun copy(irElement: IrElement, parent: IrClass): IrElement {
// This is basically modelled after the inliner copier.
class CopyIrTreeWithSymbolsForFakeOverrides(
private val overridableMember: IrOverridableMember,
typeArguments: Map<IrTypeParameterSymbol, IrType>,
private val parent: IrClass,
unimplementedOverridesStrategy: IrUnimplementedOverridesStrategy
) {
fun copy(): IrOverridableMember {
// Create new symbols.
irElement.acceptVoid(symbolRemapper)
overridableMember.acceptVoid(symbolRemapper)
// Make symbol remapper aware of the callsite's type arguments.
// Copy IR.
val result = irElement.transform(if (parent.isEffectivelyExternal()) copierMakingExternal else copier, data = null)
val result = overridableMember.transform(
if (parent.isEffectivelyExternal()) copierMakingExternal else copier,
data = null
) as IrOverridableMember
result.patchDeclarationParents(parent)
return result
}
@@ -82,10 +90,14 @@ class DeepCopyIrTreeWithSymbolsForFakeOverrides(typeArguments: Map<IrTypeParamet
typeArguments,
NullDescriptorsRemapper
)
private val copier = FakeOverrideCopier(
symbolRemapper,
FakeOverrideTypeRemapper(symbolRemapper, typeArguments),
SymbolRenamer.DEFAULT
SymbolRenamer.DEFAULT,
makeExternal = false,
parent,
unimplementedOverridesStrategy
)
private val copierMakingExternal = FakeOverrideCopier(
@@ -93,5 +105,7 @@ class DeepCopyIrTreeWithSymbolsForFakeOverrides(typeArguments: Map<IrTypeParamet
FakeOverrideTypeRemapper(symbolRemapper, typeArguments),
SymbolRenamer.DEFAULT,
makeExternal = true,
parent,
unimplementedOverridesStrategy
)
}
@@ -12,48 +12,20 @@ class FakeOverrideCopier(
private val symbolRemapper: SymbolRemapper,
private val typeRemapper: TypeRemapper,
private val symbolRenamer: SymbolRenamer,
private val makeExternal: Boolean = false,
private val makeExternal: Boolean,
private val parent: IrClass,
private val unimplementedOverridesStrategy: IrUnimplementedOverridesStrategy
) : 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 {
val customization = unimplementedOverridesStrategy.computeCustomization(declaration, parent)
override fun visitSimpleFunction(declaration: IrSimpleFunction): IrSimpleFunction =
declaration.factory.createFunctionWithLateBinding(
return declaration.factory.createFunctionWithLateBinding(
declaration.startOffset, declaration.endOffset,
IrDeclarationOrigin.FAKE_OVERRIDE,
customization.origin ?: IrDeclarationOrigin.FAKE_OVERRIDE,
symbolRenamer.getFunctionName(declaration.symbol),
declaration.visibility,
declaration.modality,
customization.modality ?: declaration.modality,
declaration.returnType,
isInline = declaration.isInline,
isExternal = makeExternal,
@@ -63,17 +35,50 @@ class FakeOverrideCopier(
isOperator = declaration.isOperator,
isInfix = declaration.isInfix
).apply {
transformFunctionChildren(declaration)
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)
valueParameters = declaration.valueParameters.transform()
if (customization.needToCreateBody && body == null) {
body = factory.createBlockBody(startOffset, endOffset)
}
}
}
}
override fun visitProperty(declaration: IrProperty): IrProperty {
val customization = unimplementedOverridesStrategy.computeCustomization(declaration, parent)
override fun visitProperty(declaration: IrProperty): IrProperty =
declaration.factory.createPropertyWithLateBinding(
return declaration.factory.createPropertyWithLateBinding(
declaration.startOffset, declaration.endOffset,
IrDeclarationOrigin.FAKE_OVERRIDE,
customization.origin ?: IrDeclarationOrigin.FAKE_OVERRIDE,
declaration.name,
declaration.visibility,
declaration.modality,
customization.modality ?: declaration.modality,
isVar = declaration.isVar,
isConst = declaration.isConst,
isLateinit = declaration.isLateinit,
@@ -85,6 +90,7 @@ class FakeOverrideCopier(
this.getter = declaration.getter?.transform()
this.setter = declaration.setter?.transform()
}
}
override fun visitValueParameter(declaration: IrValueParameter): IrValueParameter =
declaration.factory.createValueParameter(
@@ -17,10 +17,12 @@ import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.TypeCheckerState
import org.jetbrains.kotlin.types.Variance
abstract class FakeOverrideBuilderStrategy(private val friendModules: Map<String, Collection<String>>) {
abstract class FakeOverrideBuilderStrategy(
private val friendModules: Map<String, Collection<String>>,
private val unimplementedOverridesStrategy: IrUnimplementedOverridesStrategy
) {
open fun fakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass): IrOverridableMember =
buildFakeOverrideMember(superType, member, clazz, friendModules)
buildFakeOverrideMember(superType, member, clazz, friendModules, unimplementedOverridesStrategy)
fun linkFakeOverride(fakeOverride: IrOverridableMember, compatibilityMode: Boolean) {
when (fakeOverride) {
@@ -61,11 +63,13 @@ private fun isInFriendModules(
return toModuleName in fromFriends
}
fun buildFakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass): IrOverridableMember {
return buildFakeOverrideMember(superType, member, clazz, emptyMap())
}
fun buildFakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass, friendModules: Map<String, Collection<String>>): IrOverridableMember {
fun buildFakeOverrideMember(
superType: IrType,
member: IrOverridableMember,
clazz: IrClass,
friendModules: Map<String, Collection<String>> = emptyMap(),
unimplementedOverridesStrategy: IrUnimplementedOverridesStrategy = IrUnimplementedOverridesStrategy.ProcessAsFakeOverrides
): IrOverridableMember {
require(superType is IrSimpleType) { "superType is $superType, expected IrSimpleType" }
val classifier = superType.classifier
require(classifier is IrClassSymbol) { "superType classifier is not IrClassSymbol: $classifier" }
@@ -86,13 +90,12 @@ fun buildFakeOverrideMember(superType: IrType, member: IrOverridableMember, claz
substitutionMap[tp.symbol] = ta.type
}
val copier = DeepCopyIrTreeWithSymbolsForFakeOverrides(substitutionMap)
val deepCopyFakeOverride = copier.copy(member, clazz) as IrOverridableMember
deepCopyFakeOverride.parent = clazz
if (deepCopyFakeOverride.isPrivateToThisModule(clazz, classifier.owner, friendModules))
deepCopyFakeOverride.visibility = DescriptorVisibilities.INVISIBLE_FAKE
return deepCopyFakeOverride
return CopyIrTreeWithSymbolsForFakeOverrides(member, substitutionMap, clazz, unimplementedOverridesStrategy)
.copy()
.apply {
if (isPrivateToThisModule(clazz, classifier.owner, friendModules))
visibility = DescriptorVisibilities.INVISIBLE_FAKE
}
}
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.overrides
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrOverridableMember
interface IrUnimplementedOverridesStrategy {
class Customization(val origin: IrDeclarationOrigin?, val modality: Modality?, val needToCreateBody: Boolean) {
companion object {
val NO = Customization(null, null, false)
}
}
fun <T : IrOverridableMember> computeCustomization(overridableMember: T, parent: IrClass): Customization
object ProcessAsFakeOverrides : IrUnimplementedOverridesStrategy {
override fun <T : IrOverridableMember> computeCustomization(overridableMember: T, parent: IrClass) = Customization.NO
}
}
@@ -16,6 +16,8 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy
import org.jetbrains.kotlin.ir.overrides.IrOverridingUtil
import org.jetbrains.kotlin.ir.overrides.IrUnimplementedOverridesStrategy
import org.jetbrains.kotlin.ir.overrides.IrUnimplementedOverridesStrategy.ProcessAsFakeOverrides
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrPropertySymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
@@ -24,7 +26,6 @@ import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.ir.types.impl.IrErrorClassImpl
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
@@ -1101,8 +1102,10 @@ val IrFunction.allParametersCount: Int
// This is essentially the same as FakeOverrideBuilder,
// but it bypasses SymbolTable.
// TODO: merge it with FakeOverrideBuilder.
private class FakeOverrideBuilderForLowerings : FakeOverrideBuilderStrategy(emptyMap()) {
private class FakeOverrideBuilderForLowerings : FakeOverrideBuilderStrategy(
friendModules = emptyMap(),
unimplementedOverridesStrategy = ProcessAsFakeOverrides
) {
override fun linkFunctionFakeOverride(declaration: IrFunctionWithLateBinding, compatibilityMode: Boolean) {
declaration.acquireSymbol(IrSimpleFunctionSymbolImpl())
}