[IR] Split FakeOverrideBuilder to two parts

Now there is separate class encapsulating logic about how to build
fakeOverrides and one encapsulating logic of which classes
do need building fake overrides.

This also allows to untie strange inheritance dependencies.

^KT-61934
This commit is contained in:
Pavel Kunyavskiy
2023-09-14 14:14:31 +02:00
committed by Space Team
parent fcca73e900
commit 2b8b6a2b21
13 changed files with 99 additions and 82 deletions
@@ -6,8 +6,8 @@
package org.jetbrains.kotlin.backend.common.actualizer
import org.jetbrains.kotlin.backend.common.linkage.partial.PartialLinkageSupportForLinker
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
import org.jetbrains.kotlin.backend.common.overrides.FileLocalAwareLinker
import org.jetbrains.kotlin.backend.common.overrides.IrLinkerFakeOverrideProvider
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
@@ -70,7 +70,7 @@ class FakeOverrideRebuilder(
// Map from the old fake override symbol to the new (rebuilt) symbol.
private val fakeOverrideMap = hashMapOf<IrSymbol, IrSymbol>()
private val fakeOverrideBuilder = FakeOverrideBuilder(
private val fakeOverrideBuilder = IrLinkerFakeOverrideProvider(
LocalFakeOverridesStorage(),
symbolTable,
mangler,
@@ -1225,11 +1225,8 @@ val IrFunction.allParameters: List<IrValueParameter>
val IrFunction.allParametersCount: Int
get() = if (this is IrConstructor) explicitParametersCount + 1 else explicitParametersCount
// This is essentially the same as FakeOverrideBuilder,
// but it bypasses SymbolTable.
// TODO: merge it with FakeOverrideBuilder.
private class FakeOverrideBuilderForLowerings : FakeOverrideBuilderStrategy(
friendModules = emptyMap(),
private object BindToNewEmptySymbols : FakeOverrideBuilderStrategy(
friendModules = emptyMap(), // TODO: this is probably not correct. Should be fixed by KT-61384. But it's not important for current usages
unimplementedOverridesStrategy = ProcessAsFakeOverrides
) {
override fun linkFunctionFakeOverride(function: IrFunctionWithLateBinding, manglerCompatibleMode: Boolean) {
@@ -1259,7 +1256,7 @@ fun IrClass.addFakeOverrides(
implementedMembers: List<IrOverridableMember> = emptyList(),
ignoredParentSymbols: List<IrSymbol> = emptyList()
) {
IrOverridingUtil(typeSystem, FakeOverrideBuilderForLowerings(), emptyList())
IrOverridingUtil(typeSystem, BindToNewEmptySymbols, emptyList())
.buildFakeOverridesForClassUsingOverriddenSymbols(this,
implementedMembers = implementedMembers,
compatibilityMode = false,
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.backend.common.linkage.partial
import org.jetbrains.kotlin.backend.common.linkage.partial.PartialLinkageUtils.guessName
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
import org.jetbrains.kotlin.backend.common.overrides.IrLinkerFakeOverrideProvider
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.types.error.ErrorUtils
*
* Note: This is a special type of [IrProvider]. It should not be used in row with other IR providers, because it may bring to
* undesired situation when stubs for unbound fake override symbols are generated even before the corresponding call of
* [FakeOverrideBuilder.provideFakeOverrides] is made leaving no chance for proper linkage of fake overrides. This IR provider
* [IrLinkerFakeOverrideProvider.provideFakeOverrides] is made leaving no chance for proper linkage of fake overrides. This IR provider
* should be applied only after the fake overrides generation.
*/
internal class MissingDeclarationStubGenerator(private val builtIns: IrBuiltIns) : IrProvider {
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.backend.common.linkage.partial
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
import org.jetbrains.kotlin.backend.common.overrides.IrLinkerFakeOverrideProvider
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
@@ -32,7 +32,7 @@ interface PartialLinkageSupportForLinker {
* Note: Those classifiers that were detected as partially linked are excluded from the fake overrides generation
* to avoid failing with `Symbol for <signature> is unbound` error or generating fake overrides with incorrect signatures.
*/
fun exploreClassifiers(fakeOverrideBuilder: FakeOverrideBuilder)
fun exploreClassifiers(fakeOverrideBuilder: IrLinkerFakeOverrideProvider)
/**
* For local use only in inline lazy-IR functions.
@@ -58,7 +58,7 @@ interface PartialLinkageSupportForLinker {
val DISABLED = object : PartialLinkageSupportForLinker {
override val isEnabled get() = false
override fun shouldBeSkipped(declaration: IrDeclaration) = true
override fun exploreClassifiers(fakeOverrideBuilder: FakeOverrideBuilder) = Unit
override fun exploreClassifiers(fakeOverrideBuilder: IrLinkerFakeOverrideProvider) = Unit
override fun exploreClassifiersInInlineLazyIrFunction(function: IrFunction) = Unit
override fun generateStubsAndPatchUsages(symbolTable: SymbolTable, roots: () -> Sequence<IrModuleFragment>) = Unit
override fun generateStubsAndPatchUsages(symbolTable: SymbolTable, root: IrDeclaration) = Unit
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.backend.common.linkage.partial
import org.jetbrains.kotlin.backend.common.linkage.issues.PartialLinkageErrorsLogged
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
import org.jetbrains.kotlin.backend.common.overrides.IrLinkerFakeOverrideProvider
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFunction
@@ -41,7 +41,7 @@ internal class PartialLinkageSupportForLinkerImpl(
override fun shouldBeSkipped(declaration: IrDeclaration) = patcher.shouldBeSkipped(declaration)
override fun exploreClassifiers(fakeOverrideBuilder: FakeOverrideBuilder) {
override fun exploreClassifiers(fakeOverrideBuilder: IrLinkerFakeOverrideProvider) {
val entries = fakeOverrideBuilder.fakeOverrideCandidates
if (entries.isEmpty()) return
@@ -23,10 +23,12 @@ import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable
import org.jetbrains.kotlin.backend.common.serialization.GlobalDeclarationTable
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureFactory
import org.jetbrains.kotlin.backend.common.serialization.signature.PublicIdSignatureComputer
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.declarations.buildProperty
import org.jetbrains.kotlin.ir.builders.declarations.buildTypeParameter
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.linkage.partial.IrUnimplementedOverridesStrategy
import org.jetbrains.kotlin.ir.linkage.partial.IrUnimplementedOverridesStrategy.ProcessAsFakeOverrides
import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy
import org.jetbrains.kotlin.ir.overrides.IrExternalOverridabilityCondition
@@ -72,64 +74,18 @@ object DefaultFakeOverrideClassFilter : FakeOverrideClassFilter {
override fun needToConstructFakeOverrides(clazz: IrClass): Boolean = true
}
class FakeOverrideBuilder(
private class IrLinkerFakeOverrideBuilderStrategy(
val linker: FileLocalAwareLinker,
val symbolTable: SymbolTable,
mangler: KotlinMangler.IrMangler,
typeSystem: IrTypeSystemContext,
friendModules: Map<String, Collection<String>>,
private val irBuiltIns: IrBuiltIns,
private val partialLinkageSupport: PartialLinkageSupportForLinker,
val platformSpecificClassFilter: FakeOverrideClassFilter = DefaultFakeOverrideClassFilter,
private val fakeOverrideDeclarationTable: DeclarationTable = FakeOverrideDeclarationTable(mangler) { builder, table ->
IdSignatureFactory(builder, table)
},
externalOverridabilityConditions: List<IrExternalOverridabilityCondition> = emptyList(),
private val fakeOverrideDeclarationTable: DeclarationTable,
friendModules: Map<String, Collection<String>>,
unimplementedOverridesStrategy: IrUnimplementedOverridesStrategy,
) : FakeOverrideBuilderStrategy(
friendModules = friendModules,
unimplementedOverridesStrategy = if (partialLinkageSupport.isEnabled)
ImplementAsErrorThrowingStubs(partialLinkageSupport)
else
ProcessAsFakeOverrides
unimplementedOverridesStrategy = unimplementedOverridesStrategy
) {
private val haveFakeOverrides = mutableSetOf<IrClass>()
private val irOverridingUtil = IrOverridingUtil(typeSystem, this, externalOverridabilityConditions)
private val irBuiltIns = typeSystem.irBuiltIns
// TODO: The declaration table is needed for the signaturer.
// private val fakeOverrideDeclarationTable = FakeOverrideDeclarationTable(mangler, signatureSerializerFactory)
val fakeOverrideCandidates = mutableMapOf<IrClass, CompatibilityMode>()
fun enqueueClass(clazz: IrClass, signature: IdSignature, compatibilityMode: CompatibilityMode) {
fakeOverrideDeclarationTable.assumeDeclarationSignature(clazz, signature)
fakeOverrideCandidates[clazz] = compatibilityMode
}
private fun buildFakeOverrideChainsForClass(clazz: IrClass, compatibilityMode: CompatibilityMode): Boolean {
if (haveFakeOverrides.contains(clazz)) return true
for (supertype in clazz.superTypes) {
val superClass = supertype.getClass() ?: error("Unexpected super type: ${supertype.render()}")
val mode = fakeOverrideCandidates[superClass] ?: compatibilityMode
if (buildFakeOverrideChainsForClass(superClass, mode))
haveFakeOverrides.add(superClass)
}
if (!platformSpecificClassFilter.needToConstructFakeOverrides(clazz)) return false
buildFakeOverridesForSingleClass(clazz, compatibilityMode)
return true
}
fun buildFakeOverridesForSingleClass(clazz: IrClass, compatibilityMode: CompatibilityMode) {
fakeOverrideDeclarationTable.run {
inFile(clazz.fileOrNull) {
irOverridingUtil.buildFakeOverridesForClass(clazz, compatibilityMode.oldSignatures)
}
}
}
override fun linkFunctionFakeOverride(function: IrFunctionWithLateBinding, manglerCompatibleMode: Boolean) {
val (signature, symbol) = computeFunctionFakeOverrideSymbol(function, manglerCompatibleMode)
@@ -278,6 +234,70 @@ class FakeOverrideBuilder(
getter = property.getter?.let { buildFunctionWithDisambiguatedSignature(it) }
setter = property.setter?.let { buildFunctionWithDisambiguatedSignature(it) }
}
}
class IrLinkerFakeOverrideProvider(
linker: FileLocalAwareLinker,
symbolTable: SymbolTable,
mangler: KotlinMangler.IrMangler,
typeSystem: IrTypeSystemContext,
friendModules: Map<String, Collection<String>>,
private val partialLinkageSupport: PartialLinkageSupportForLinker,
val platformSpecificClassFilter: FakeOverrideClassFilter = DefaultFakeOverrideClassFilter,
private val fakeOverrideDeclarationTable: DeclarationTable = FakeOverrideDeclarationTable(mangler) { builder, table ->
IdSignatureFactory(builder, table)
},
externalOverridabilityConditions: List<IrExternalOverridabilityCondition> = emptyList(),
) {
private val irOverridingUtil = IrOverridingUtil(
typeSystem,
IrLinkerFakeOverrideBuilderStrategy(
linker,
symbolTable,
typeSystem.irBuiltIns,
partialLinkageSupport,
fakeOverrideDeclarationTable,
friendModules,
if (partialLinkageSupport.isEnabled)
ImplementAsErrorThrowingStubs(partialLinkageSupport)
else
ProcessAsFakeOverrides
),
externalOverridabilityConditions
)
private val haveFakeOverrides = mutableSetOf<IrClass>()
val fakeOverrideCandidates = mutableMapOf<IrClass, CompatibilityMode>()
fun enqueueClass(clazz: IrClass, signature: IdSignature, compatibilityMode: CompatibilityMode) {
fakeOverrideDeclarationTable.assumeDeclarationSignature(clazz, signature)
fakeOverrideCandidates[clazz] = compatibilityMode
}
private fun buildFakeOverrideChainsForClass(clazz: IrClass, compatibilityMode: CompatibilityMode): Boolean {
if (haveFakeOverrides.contains(clazz)) return true
for (supertype in clazz.superTypes) {
val superClass = supertype.getClass() ?: error("Unexpected super type: ${supertype.render()}")
val mode = fakeOverrideCandidates[superClass] ?: compatibilityMode
if (buildFakeOverrideChainsForClass(superClass, mode))
haveFakeOverrides.add(superClass)
}
if (!platformSpecificClassFilter.needToConstructFakeOverrides(clazz)) return false
buildFakeOverridesForSingleClass(clazz, compatibilityMode)
return true
}
fun buildFakeOverridesForSingleClass(clazz: IrClass, compatibilityMode: CompatibilityMode) {
fakeOverrideDeclarationTable.run {
inFile(clazz.fileOrNull) {
irOverridingUtil.buildFakeOverridesForClass(clazz, compatibilityMode.oldSignatures)
}
}
}
fun provideFakeOverrides(klass: IrClass, compatibilityMode: CompatibilityMode) {
buildFakeOverrideChainsForClass(klass, compatibilityMode)
@@ -7,8 +7,8 @@ package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.backend.common.linkage.issues.IrDisallowedErrorNode
import org.jetbrains.kotlin.backend.common.linkage.issues.IrSymbolTypeMismatchException
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideClassFilter
import org.jetbrains.kotlin.backend.common.overrides.IrLinkerFakeOverrideProvider
import org.jetbrains.kotlin.backend.common.serialization.encodings.*
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData.SymbolKind
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData.SymbolKind.*
@@ -75,7 +75,7 @@ class IrDeclarationDeserializer(
private var deserializeBodies: Boolean,
val symbolDeserializer: IrSymbolDeserializer,
private val platformFakeOverrideClassFilter: FakeOverrideClassFilter,
private val fakeOverrideBuilder: FakeOverrideBuilder,
private val fakeOverrideBuilder: IrLinkerFakeOverrideProvider,
private val compatibilityMode: CompatibilityMode,
private val partialLinkageEnabled: Boolean,
private val internationService: IrInterningService,
@@ -7,8 +7,8 @@ package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.backend.common.linkage.issues.*
import org.jetbrains.kotlin.backend.common.linkage.partial.PartialLinkageSupportForLinker
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
import org.jetbrains.kotlin.backend.common.overrides.FileLocalAwareLinker
import org.jetbrains.kotlin.backend.common.overrides.IrLinkerFakeOverrideProvider
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -47,7 +47,7 @@ abstract class KotlinIrLinker(
protected val deserializersForModules = linkedMapOf<String, IrModuleDeserializer>()
abstract val fakeOverrideBuilder: FakeOverrideBuilder
abstract val fakeOverrideBuilder: IrLinkerFakeOverrideProvider
abstract val translationPluginContext: TranslationPluginContext?
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
import org.jetbrains.kotlin.backend.common.linkage.partial.PartialLinkageSupportForLinker
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
import org.jetbrains.kotlin.backend.common.overrides.IrLinkerFakeOverrideProvider
import org.jetbrains.kotlin.backend.common.serialization.*
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.IrBuiltIns
@@ -39,7 +39,7 @@ class JsIrLinker(
symbol
}) {
override val fakeOverrideBuilder = FakeOverrideBuilder(
override val fakeOverrideBuilder = IrLinkerFakeOverrideProvider(
linker = this,
symbolTable = symbolTable,
mangler = JsManglerIr,
@@ -7,9 +7,9 @@ package org.jetbrains.kotlin.backend.jvm.serialization
import org.jetbrains.kotlin.backend.common.linkage.partial.PartialLinkageSupportForLinker
import org.jetbrains.kotlin.backend.common.overrides.DefaultFakeOverrideClassFilter
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideDeclarationTable
import org.jetbrains.kotlin.backend.common.overrides.FileLocalAwareLinker
import org.jetbrains.kotlin.backend.common.overrides.IrLinkerFakeOverrideProvider
import org.jetbrains.kotlin.backend.common.serialization.*
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureFactory
@@ -149,8 +149,8 @@ fun makeSimpleFakeOverrideBuilder(
symbolTable: SymbolTable,
typeSystemContext: IrTypeSystemContext,
symbolDeserializer: IrSymbolDeserializer
): FakeOverrideBuilder {
return FakeOverrideBuilder(
): IrLinkerFakeOverrideProvider {
return IrLinkerFakeOverrideProvider(
object : FileLocalAwareLinker {
override fun tryReferencingPropertyByLocalSignature(parent: IrDeclaration, idSignature: IdSignature): IrPropertySymbol =
symbolDeserializer.referencePropertyByLocalSignature(idSignature)
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.ir.backend.jvm.serialization
import org.jetbrains.kotlin.backend.common.linkage.partial.PartialLinkageSupportForLinker
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
import org.jetbrains.kotlin.backend.common.overrides.IrLinkerFakeOverrideProvider
import org.jetbrains.kotlin.backend.common.serialization.*
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
import org.jetbrains.kotlin.descriptors.*
@@ -44,7 +44,7 @@ class JvmIrLinker(
private val enableIdSignatures: Boolean,
) : KotlinIrLinker(currentModule, messageLogger, typeSystem.irBuiltIns, symbolTable, emptyList()) {
override val fakeOverrideBuilder = FakeOverrideBuilder(
override val fakeOverrideBuilder = IrLinkerFakeOverrideProvider(
linker = this,
symbolTable = symbolTable,
mangler = JvmIrMangler,
@@ -18,8 +18,8 @@ package org.jetbrains.kotlin.backend.konan.serialization
import org.jetbrains.kotlin.backend.common.linkage.issues.UserVisibleIrModulesSupport
import org.jetbrains.kotlin.backend.common.linkage.partial.PartialLinkageSupportForLinker
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideClassFilter
import org.jetbrains.kotlin.backend.common.overrides.IrLinkerFakeOverrideProvider
import org.jetbrains.kotlin.backend.common.serialization.*
import org.jetbrains.kotlin.backend.common.serialization.proto.IdSignature as ProtoIdSignature
import org.jetbrains.kotlin.backend.konan.CacheDeserializationStrategy
@@ -314,7 +314,7 @@ internal class KonanIrLinker(
KonanForwardDeclarationModuleDeserializer(it, this, stubGenerator)
}
override val fakeOverrideBuilder = FakeOverrideBuilder(
override val fakeOverrideBuilder = IrLinkerFakeOverrideProvider(
linker = this,
symbolTable = symbolTable,
mangler = KonanManglerIr,
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.cli.klib
// TODO: Extract `library` package as a shared jar?
import org.jetbrains.kotlin.backend.common.linkage.partial.PartialLinkageSupportForLinker
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
import org.jetbrains.kotlin.backend.common.overrides.IrLinkerFakeOverrideProvider
import org.jetbrains.kotlin.backend.common.serialization.BasicIrModuleDeserializer
import org.jetbrains.kotlin.backend.common.serialization.DeserializationStrategy
import org.jetbrains.kotlin.backend.common.serialization.IrModuleDeserializer
@@ -194,7 +194,7 @@ class Library(val libraryNameOrPath: String, val requestedRepository: String?, v
class KlibToolLinker(
module: ModuleDescriptor, irBuiltIns: IrBuiltIns, symbolTable: SymbolTable
) : KotlinIrLinker(module, KlibToolLogger, irBuiltIns, symbolTable, emptyList()) {
override val fakeOverrideBuilder = FakeOverrideBuilder(
override val fakeOverrideBuilder = IrLinkerFakeOverrideProvider(
linker = this,
symbolTable = symbolTable,
mangler = KonanManglerIr,