[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
@@ -21,9 +21,14 @@ import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable
import org.jetbrains.kotlin.backend.common.serialization.GlobalDeclarationTable
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer
import org.jetbrains.kotlin.backend.common.serialization.signature.PublicIdSignatureComputer
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedDeclarationsProcessor.Companion.MISSING_ABSTRACT_CALLABLE_MEMBER_IMPLEMENTATION
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.declarations.*
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.Customization
import org.jetbrains.kotlin.ir.overrides.IrUnimplementedOverridesStrategy.ProcessAsFakeOverrides
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrPropertySymbolImpl
@@ -63,17 +68,36 @@ object DefaultFakeOverrideClassFilter : FakeOverrideClassFilter {
override fun needToConstructFakeOverrides(clazz: IrClass): Boolean = true
}
private object ImplementAsErrorThrowingStubs : IrUnimplementedOverridesStrategy {
override fun <T : IrOverridableMember> computeCustomization(overridableMember: T, parent: IrClass) =
if (overridableMember.modality == Modality.ABSTRACT
&& parent.modality != Modality.ABSTRACT
&& parent.modality != Modality.SEALED
) {
Customization(
origin = MISSING_ABSTRACT_CALLABLE_MEMBER_IMPLEMENTATION,
modality = parent.modality, // Use modality of class for implemented callable member.
needToCreateBody = true // At least it should have empty body. Later, the body will be patched in UnlinkedDeclarationsProcessor.
)
} else
Customization.NO
}
class FakeOverrideBuilder(
val linker: FileLocalAwareLinker,
val symbolTable: SymbolTable,
mangler: KotlinMangler.IrMangler,
typeSystem: IrTypeSystemContext,
friendModules: Map<String, Collection<String>>,
partialLinkageEnabled: Boolean,
val platformSpecificClassFilter: FakeOverrideClassFilter = DefaultFakeOverrideClassFilter,
private val fakeOverrideDeclarationTable: DeclarationTable = FakeOverrideDeclarationTable(mangler) { builder, table ->
IdSignatureSerializer(builder, table)
}
) : FakeOverrideBuilderStrategy(friendModules) {
) : FakeOverrideBuilderStrategy(
friendModules = friendModules,
unimplementedOverridesStrategy = if (partialLinkageEnabled) ImplementAsErrorThrowingStubs else ProcessAsFakeOverrides
) {
private val haveFakeOverrides = mutableSetOf<IrClass>()
private val irOverridingUtil = IrOverridingUtil(typeSystem, this)
@@ -1,90 +0,0 @@
/*
* 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.backend.common.serialization.unlinked
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.util.*
internal inline fun <reified T : IrOverridableDeclaration<*>> T.deepCopyWithImplementedFakeOverrides(): T {
val clazz = parentAsClass
return deepCopyWithSymbols(clazz, DeepCopySymbolRemapperPreservingSignatures()) { symbolRemapper, typeRemapper ->
ImplementedFakeOverrideCopier(clazz, symbolRemapper, typeRemapper)
}
}
internal class ImplementedFakeOverrideCopier(
private val clazz: IrClass,
private val symbolRemapper: SymbolRemapper,
private val typeRemapper: TypeRemapper
) : DeepCopyIrTreeWithSymbols(symbolRemapper, typeRemapper) {
override fun visitProperty(declaration: IrProperty): IrProperty =
declaration.factory.createProperty(
startOffset = declaration.startOffset,
endOffset = declaration.endOffset,
origin = MISSING_ABSTRACT_CALLABLE_MEMBER_IMPLEMENTATION, // Customized.
symbol = symbolRemapper.getDeclaredProperty(declaration.symbol),
name = declaration.name,
visibility = declaration.visibility,
modality = clazz.modality, // Customized.
isVar = declaration.isVar,
isConst = declaration.isConst,
isLateinit = declaration.isLateinit,
isDelegated = declaration.isDelegated,
isExternal = declaration.isExternal,
isExpect = declaration.isExpect,
isFakeOverride = false, // Customized.
containerSource = declaration.containerSource,
).apply {
overriddenSymbols = declaration.overriddenSymbols.map { symbolRemapper.getReferencedProperty(it) }
copyAttributes(declaration)
transformAnnotations(declaration)
backingField = declaration.backingField?.transform()?.also { it.correspondingPropertySymbol = symbol }
getter = declaration.getter?.transform()?.also { it.correspondingPropertySymbol = symbol }
setter = declaration.setter?.transform()?.also { it.correspondingPropertySymbol = symbol }
}
override fun visitSimpleFunction(declaration: IrSimpleFunction): IrSimpleFunction =
declaration.factory.createFunction(
startOffset = declaration.startOffset,
endOffset = declaration.endOffset,
origin = MISSING_ABSTRACT_CALLABLE_MEMBER_IMPLEMENTATION, // Customized.
symbol = symbolRemapper.getDeclaredFunction(declaration.symbol),
name = declaration.name,
visibility = declaration.visibility,
modality = clazz.modality, // Customized.
returnType = declaration.returnType,
isInline = declaration.isInline,
isExternal = declaration.isExternal,
isTailrec = declaration.isTailrec,
isSuspend = declaration.isSuspend,
isOperator = declaration.isOperator,
isInfix = declaration.isInfix,
isExpect = declaration.isExpect,
isFakeOverride = false, // Customized.
containerSource = declaration.containerSource,
).apply {
overriddenSymbols = declaration.overriddenSymbols.map { symbolRemapper.getReferencedFunction(it) as IrSimpleFunctionSymbol }
contextReceiverParametersCount = declaration.contextReceiverParametersCount
copyAttributes(declaration)
transformAnnotations(this)
copyTypeParametersFrom(declaration)
typeRemapper.withinScope(this) {
dispatchReceiverParameter = declaration.dispatchReceiverParameter?.transform()
extensionReceiverParameter = declaration.extensionReceiverParameter?.transform()
returnType = typeRemapper.remapType(declaration.returnType)
valueParameters = declaration.valueParameters.transform()
body = factory.createBlockBody(
declaration.body?.startOffset ?: declaration.startOffset,
declaration.body?.endOffset ?: declaration.endOffset
) // the body should be empty
}
}
}
private val MISSING_ABSTRACT_CALLABLE_MEMBER_IMPLEMENTATION =
object : IrDeclarationOriginImpl("MISSING_ABSTRACT_CALLABLE_MEMBER_IMPLEMENTATION", isSynthetic = true) {}
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.backend.common.serialization.unlinked.PartialLinkage
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedIrElementRenderer.appendDeclaration
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedIrElementRenderer.renderError
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UsedClassifierSymbolStatus.Companion.isUnlinked
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
@@ -60,31 +59,11 @@ internal class UnlinkedDeclarationsProcessor(
fun signatureTransformer(): IrElementTransformerVoid = SignatureTransformer()
private inner class SignatureTransformer : IrElementTransformerVoid() {
private val implementedFakeOverrideProperties = hashSetOf<IrProperty>()
private val IrFunction.isAccessorOfImplementedFakeOverrideProperty: Boolean
get() = (this as? IrSimpleFunction)?.correspondingPropertySymbol?.owner in implementedFakeOverrideProperties
override fun visitProperty(declaration: IrProperty): IrStatement {
val newProperty = declaration.replaceIfUnimplementedFakeOverride()
val isImplementedFakeOverride = newProperty != declaration
if (isImplementedFakeOverride) implementedFakeOverrideProperties += newProperty
newProperty.transformChildrenVoid()
if (isImplementedFakeOverride) implementedFakeOverrideProperties -= newProperty
return newProperty
}
override fun visitFunction(declaration: IrFunction): IrStatement {
val newFunction = declaration.replaceIfUnimplementedFakeOverride()
val removedUnlinkedTypes = newFunction.fixUnlinkedTypes()
val removedUnlinkedTypes = declaration.fixUnlinkedTypes()
val isImplementedFakeOverride = declaration.origin == MISSING_ABSTRACT_CALLABLE_MEMBER_IMPLEMENTATION
val isImplementedFakeOverride = newFunction != declaration || declaration.isAccessorOfImplementedFakeOverrideProperty
return newFunction.transformBodyIfNecessary(isImplementedFakeOverride, removedUnlinkedTypes)
return declaration.transformBodyIfNecessary(isImplementedFakeOverride, removedUnlinkedTypes)
}
override fun visitField(declaration: IrField): IrStatement {
@@ -111,19 +90,6 @@ internal class UnlinkedDeclarationsProcessor(
return declaration
}
/**
* Replaces an [IrProperty] or [IrSimpleFunction] that is abstract fake override in non-abstract class
* by the corresponding non-abstract IR element.
*/
private fun <T : IrDeclaration> T.replaceIfUnimplementedFakeOverride(): T {
if (this !is IrOverridableDeclaration<*> || !isFakeOverride || modality != Modality.ABSTRACT) return this
val clazz = parentAsClass
if (clazz.modality == Modality.ABSTRACT || clazz.modality == Modality.SEALED) return this
return deepCopyWithImplementedFakeOverrides()
}
/**
* Returns the set of all unlinked types encountered during transformation of the given [IrFunction].
* Or empty set if there were no unlinked types.
@@ -363,6 +329,9 @@ internal class UnlinkedDeclarationsProcessor(
companion object {
private val ERROR_ORIGIN = object : IrStatementOriginImpl("LINKAGE ERROR") {}
val MISSING_ABSTRACT_CALLABLE_MEMBER_IMPLEMENTATION =
object : IrDeclarationOriginImpl("MISSING_ABSTRACT_CALLABLE_MEMBER_IMPLEMENTATION", isSynthetic = true) {}
}
}