[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,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?