[Private fake overrides] Private fake override construction

This commit is contained in:
Alexander Gorshenev
2020-10-21 22:40:18 +03:00
parent c90556a883
commit 223d1dd5e6
8 changed files with 63 additions and 58 deletions
@@ -101,26 +101,16 @@ class IrOverridingUtil(
} }
} }
// We need to get Any's members if all the parents are private.
private fun allPublicApiSuperTypesOrAny(clazz: IrClass): List<IrType> {
val superTypes = clazz.superTypes
val superClasses = superTypes.map { it.getClass() ?: error("Unexpected super type: $it") }
return if (superClasses.isEmpty() || superClasses.any { it.symbol.isPublicApi })
superTypes
else
listOf(irBuiltIns.anyType)
}
fun buildFakeOverridesForClass(clazz: IrClass) { fun buildFakeOverridesForClass(clazz: IrClass) {
val superTypes = allPublicApiSuperTypesOrAny(clazz) val superTypes = clazz.superTypes
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val fromCurrent = clazz.declarations.filter { it is IrOverridableMember && it.symbol.isPublicApi } as List<IrOverridableMember> val fromCurrent = clazz.declarations.filter { it is IrOverridableMember } as List<IrOverridableMember>
val allFromSuper = superTypes.flatMap { superType -> val allFromSuper = superTypes.flatMap { superType ->
val superClass = superType.getClass() ?: error("Unexpected super type: $superType") val superClass = superType.getClass() ?: error("Unexpected super type: $superType")
superClass.declarations superClass.declarations
.filter { it is IrOverridableMember && it.symbol.isPublicApi } .filter { it.isOverridableMemberOrAccessor() }
.map { .map {
val overridenMember = it as IrOverridableMember val overridenMember = it as IrOverridableMember
val fakeOverride = fakeOverrideBuilder.fakeOverrideMember(superType, overridenMember, clazz) val fakeOverride = fakeOverrideBuilder.fakeOverrideMember(superType, overridenMember, clazz)
@@ -76,9 +76,6 @@ class FakeOverrideChecker(
validateFakeOverrides(declaration) validateFakeOverrides(declaration)
super.visitClass(declaration) super.visitClass(declaration)
} }
override fun visitFunction(declaration: IrFunction) {
// Don't go for function local classes
}
}) })
} }
} }
@@ -23,20 +23,13 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.descriptors.WrappedPropertyDescriptor import org.jetbrains.kotlin.ir.descriptors.WrappedPropertyDescriptor
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.ir.overrides.DeepCopyIrTreeWithSymbolsForFakeOverrides
import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy
import org.jetbrains.kotlin.ir.overrides.IrOverridingUtil import org.jetbrains.kotlin.ir.overrides.IrOverridingUtil
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrPropertySymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrPropertySymbolImpl
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.ir.types.extractTypeParameters
import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.types.Variance
class FakeOverrideGlobalDeclarationTable(signatureSerializer: IdSignatureSerializer) class FakeOverrideGlobalDeclarationTable(signatureSerializer: IdSignatureSerializer)
: GlobalDeclarationTable(signatureSerializer, signatureSerializer.mangler) { : GlobalDeclarationTable(signatureSerializer, signatureSerializer.mangler) {
@@ -54,7 +47,18 @@ class FakeOverrideDeclarationTable(
} }
} }
object DefaultFakeOverrideClassFilter : PlatformFakeOverrideClassFilter interface FakeOverrideClassFilter {
fun needToConstructFakeOverrides(clazz: IrClass): Boolean
}
interface FileLocalAwareLinker {
fun tryReferencingSimpleFunctionByLocalSignature(parent: IrDeclaration, idSignature: IdSignature): IrSimpleFunctionSymbol?
fun tryReferencingPropertyByLocalSignature(parent: IrDeclaration, idSignature: IdSignature): IrPropertySymbol?
}
object DefaultFakeOverrideClassFilter : FakeOverrideClassFilter {
override fun needToConstructFakeOverrides(clazz: IrClass): Boolean = true
}
object FakeOverrideControl { object FakeOverrideControl {
// If set to true: all fake overrides go to klib serialized IR. // If set to true: all fake overrides go to klib serialized IR.
@@ -70,15 +74,25 @@ object FakeOverrideControl {
class FakeOverrideBuilder( class FakeOverrideBuilder(
val symbolTable: SymbolTable, val symbolTable: SymbolTable,
val signaturer: IdSignatureSerializer, val signaturer: IdSignatureSerializer,
val irBuiltIns: IrBuiltIns, irBuiltIns: IrBuiltIns,
val platformSpecificClassFilter: PlatformFakeOverrideClassFilter = DefaultFakeOverrideClassFilter val platformSpecificClassFilter: FakeOverrideClassFilter = DefaultFakeOverrideClassFilter
) : FakeOverrideBuilderStrategy() { ) : FakeOverrideBuilderStrategy() {
private val haveFakeOverrides = mutableSetOf<IrClass>() private val haveFakeOverrides = mutableSetOf<IrClass>()
private val irOverridingUtil = IrOverridingUtil(irBuiltIns, this) private val irOverridingUtil = IrOverridingUtil(irBuiltIns, this)
fun buildFakeOverrideChainsForClass(clazz: IrClass) { // TODO: The declaration table is needed for the signaturer.
private val fakeOverrideDeclarationTable = FakeOverrideDeclarationTable(signaturer)
private val fakeOverrideClassQueue = mutableListOf<IrClass>()
fun enqueueClass(clazz: IrClass, signature: IdSignature) {
fakeOverrideDeclarationTable.assumeDeclarationSignature(clazz, signature)
fakeOverrideClassQueue.add(clazz)
}
private fun buildFakeOverrideChainsForClass(clazz: IrClass) {
if (haveFakeOverrides.contains(clazz)) return if (haveFakeOverrides.contains(clazz)) return
if (!platformSpecificClassFilter.constructFakeOverrides(clazz) || !clazz.symbol.isPublicApi) return if (!platformSpecificClassFilter.needToConstructFakeOverrides(clazz)) return
val superTypes = clazz.superTypes val superTypes = clazz.superTypes
@@ -127,11 +141,8 @@ class FakeOverrideBuilder(
it.correspondingPropertySymbol = tempSymbol it.correspondingPropertySymbol = tempSymbol
} }
val signature = signaturer.composePublicIdSignature(declaration) val signature = composeSignature(declaration)
declarePropertyFakeOverride(declaration, signature)
symbolTable.declarePropertyFromLinker(WrappedPropertyDescriptor(), signature) {
declaration.acquireSymbol(it)
}
declaration.getter?.let { declaration.getter?.let {
it.correspondingPropertySymbol = declaration.symbol it.correspondingPropertySymbol = declaration.symbol
@@ -149,4 +160,11 @@ class FakeOverrideBuilder(
irOverridingUtil.clear() irOverridingUtil.clear()
haveFakeOverrides.add(klass) haveFakeOverrides.add(klass)
} }
fun provideFakeOverrides() {
while (fakeOverrideClassQueue.isNotEmpty()) {
val klass = fakeOverrideClassQueue.removeLast()
provideFakeOverrides(klass)
}
}
} }
@@ -8,7 +8,8 @@ package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.backend.common.LoggingContext import org.jetbrains.kotlin.backend.common.LoggingContext
import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.common.lower.InnerClassesSupport import org.jetbrains.kotlin.backend.common.lower.InnerClassesSupport
import org.jetbrains.kotlin.backend.common.overrides.PlatformFakeOverrideClassFilter import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideClassFilter
import org.jetbrains.kotlin.backend.common.peek import org.jetbrains.kotlin.backend.common.peek
import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.backend.common.push
@@ -114,7 +115,7 @@ abstract class IrFileDeserializer(
val symbolTable: SymbolTable, val symbolTable: SymbolTable,
protected var deserializeBodies: Boolean, protected var deserializeBodies: Boolean,
private val deserializeFakeOverrides: Boolean, private val deserializeFakeOverrides: Boolean,
private val fakeOverrideQueue: MutableList<IrClass>, private val fakeOverrideBuilder: FakeOverrideBuilder,
private val allowErrorNodes: Boolean private val allowErrorNodes: Boolean
) { ) {
protected val irFactory: IrFactory get() = symbolTable.irFactory protected val irFactory: IrFactory get() = symbolTable.irFactory
@@ -134,7 +135,7 @@ abstract class IrFileDeserializer(
private val delegatedSymbolMap = mutableMapOf<IrSymbol, IrSymbol>() private val delegatedSymbolMap = mutableMapOf<IrSymbol, IrSymbol>()
abstract val deserializeInlineFunctions: Boolean abstract val deserializeInlineFunctions: Boolean
abstract val platformFakeOverrideClassFilter: PlatformFakeOverrideClassFilter abstract val platformFakeOverrideClassFilter: FakeOverrideClassFilter
fun deserializeFqName(fqn: List<Int>): String = fun deserializeFqName(fqn: List<Int>): String =
fqn.joinToString(".", transform = ::deserializeString) fqn.joinToString(".", transform = ::deserializeString)
@@ -1088,11 +1089,7 @@ abstract class IrFileDeserializer(
(descriptor as? WrappedClassDescriptor)?.bind(this) (descriptor as? WrappedClassDescriptor)?.bind(this)
if (!deserializeFakeOverrides) { fakeOverrideBuilder.enqueueClass(this, signature)
if (symbol.isPublicApi) {
fakeOverrideQueue.add(this)
}
}
} }
} }
@@ -1470,7 +1467,7 @@ abstract class IrFileDeserializer(
// or reconstruct them after IR linker completes. // or reconstruct them after IR linker completes.
private fun isSkippableFakeOverride(proto: ProtoDeclaration, parent: IrClass): Boolean { private fun isSkippableFakeOverride(proto: ProtoDeclaration, parent: IrClass): Boolean {
if (deserializeFakeOverrides) return false if (deserializeFakeOverrides) return false
if (!platformFakeOverrideClassFilter.constructFakeOverrides(parent)) return false if (!platformFakeOverrideClassFilter.needToConstructFakeOverrides(parent)) return false
val symbol = when (proto.declaratorCase!!) { val symbol = when (proto.declaratorCase!!) {
IR_FUNCTION -> deserializeIrSymbol(proto.irFunction.base.base.symbol) IR_FUNCTION -> deserializeIrSymbol(proto.irFunction.base.base.symbol)
@@ -1245,9 +1245,8 @@ open class IrFileSerializer(
assert(member.parent is IrClass) assert(member.parent is IrClass)
if (FakeOverrideControl.serializeFakeOverrides) return true if (FakeOverrideControl.serializeFakeOverrides) return true
if (backendSpecificSerializeAllMembers(member.parent as IrClass)) return true if (backendSpecificSerializeAllMembers(member.parent as IrClass)) return true
// TODO: we can, probably, maintain a privacy bit while traversing the tree
// instead of running the parent hierarchy for isExported every time. return (!member.isFakeOverride)
return !(member.isFakeOverride && declarationTable.isExportedDeclaration(member))
} }
private fun fillPlatformExplicitlyExported(file: IrFile, proto: ProtoFile.Builder) { private fun fillPlatformExplicitlyExported(file: IrFile, proto: ProtoFile.Builder) {
@@ -73,7 +73,6 @@ abstract class KotlinIrLinker(
abstract val translationPluginContext: TranslationPluginContext? abstract val translationPluginContext: TranslationPluginContext?
private val haveSeen = mutableSetOf<IrSymbol>() private val haveSeen = mutableSetOf<IrSymbol>()
private val fakeOverrideClassQueue = mutableListOf<IrClass>()
private lateinit var linkerExtensions: Collection<IrDeserializer.IrLinkerExtension> private lateinit var linkerExtensions: Collection<IrDeserializer.IrLinkerExtension>
@@ -234,7 +233,17 @@ abstract class KotlinIrLinker(
deserializeFakeOverrides: Boolean, deserializeFakeOverrides: Boolean,
private val moduleDeserializer: IrModuleDeserializer, private val moduleDeserializer: IrModuleDeserializer,
allowErrorNodes: Boolean allowErrorNodes: Boolean
) : IrFileDeserializer(logger, builtIns, symbolTable, !onlyHeaders, deserializeFakeOverrides, fakeOverrideClassQueue, allowErrorNodes) { ) :
IrFileDeserializer(
logger,
builtIns,
symbolTable,
!onlyHeaders,
deserializeFakeOverrides,
fakeOverrideBuilder,
allowErrorNodes
)
{
private var fileLoops = mutableMapOf<Int, IrLoop>() private var fileLoops = mutableMapOf<Int, IrLoop>()
@@ -600,12 +609,7 @@ abstract class KotlinIrLinker(
override fun postProcess() { override fun postProcess() {
finalizeExpectActualLinker() finalizeExpectActualLinker()
fakeOverrideBuilder.provideFakeOverrides()
while (fakeOverrideClassQueue.isNotEmpty()) {
val klass = fakeOverrideClassQueue.removeLast()
fakeOverrideBuilder.provideFakeOverrides(klass)
}
haveSeen.clear() haveSeen.clear()
// TODO: fix IrPluginContext to make it not produce additional external reference // TODO: fix IrPluginContext to make it not produce additional external reference
@@ -31,7 +31,7 @@ class JsIrLinker(
deserializeFakeOverrides: Boolean = FakeOverrideControl.deserializeFakeOverrides deserializeFakeOverrides: Boolean = FakeOverrideControl.deserializeFakeOverrides
) : KotlinIrLinker(currentModule, logger, builtIns, symbolTable, emptyList(), deserializeFakeOverrides) { ) : KotlinIrLinker(currentModule, logger, builtIns, symbolTable, emptyList(), deserializeFakeOverrides) {
override val fakeOverrideBuilder = FakeOverrideBuilder(symbolTable, IdSignatureSerializer(JsManglerIr), builtIns) override val fakeOverrideBuilder = FakeOverrideBuilder(this, symbolTable, IdSignatureSerializer(JsManglerIr), builtIns)
override fun isBuiltInModule(moduleDescriptor: ModuleDescriptor): Boolean = override fun isBuiltInModule(moduleDescriptor: ModuleDescriptor): Boolean =
moduleDescriptor === moduleDescriptor.builtIns.builtInsModule moduleDescriptor === moduleDescriptor.builtIns.builtInsModule
@@ -44,7 +44,7 @@ class JvmIrLinker(
deserializeFakeOverrides: Boolean = FakeOverrideControl.deserializeFakeOverrides deserializeFakeOverrides: Boolean = FakeOverrideControl.deserializeFakeOverrides
) : KotlinIrLinker(currentModule, logger, builtIns, symbolTable, emptyList(), deserializeFakeOverrides) { ) : KotlinIrLinker(currentModule, logger, builtIns, symbolTable, emptyList(), deserializeFakeOverrides) {
override val fakeOverrideBuilder = FakeOverrideBuilder(symbolTable, IdSignatureSerializer(JvmManglerIr), builtIns) override val fakeOverrideBuilder = FakeOverrideBuilder(this, symbolTable, IdSignatureSerializer(JvmManglerIr), builtIns)
private val javaName = Name.identifier("java") private val javaName = Name.identifier("java")