FIR: Implement delayed binding of overriddens in the delegated members

fixes the problem when overridden symbols on delegated members were
build on the incomplete fake overrides leading to the incorrect
generation of the function for default parameter and thus to the
codegen error (see withDefaultsMultipleFilesOrder test for an example)
This commit is contained in:
Ilya Chernikov
2021-06-22 17:15:45 +02:00
committed by TeamCityServer
parent c9b6847d83
commit 873a7c6ef1
7 changed files with 92 additions and 44 deletions
@@ -293,6 +293,24 @@ internal tailrec fun FirCallableSymbol<*>.unwrapCallRepresentative(root: FirCall
return overriddenSymbol.unwrapCallRepresentative(this)
}
internal fun FirSimpleFunction.processOverriddenFunctionSymbols(
containingClass: FirClass,
session: FirSession,
scopeSession: ScopeSession,
processor: (FirNamedFunctionSymbol) -> Unit
) {
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
scope.processFunctionsByName(name) {}
scope.processOverriddenFunctionsFromSuperClasses(symbol, containingClass) {
if (it.fir.visibility == Visibilities.Private) {
return@processOverriddenFunctionsFromSuperClasses ProcessorAction.NEXT
}
processor(it)
ProcessorAction.NEXT
}
}
internal fun FirSimpleFunction.generateOverriddenFunctionSymbols(
containingClass: FirClass,
session: FirSession,
@@ -301,20 +319,12 @@ internal fun FirSimpleFunction.generateOverriddenFunctionSymbols(
fakeOverrideGenerator: FakeOverrideGenerator,
): List<IrSimpleFunctionSymbol> {
val superClasses = containingClass.getSuperTypesAsIrClasses(declarationStorage) ?: return emptyList()
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
scope.processFunctionsByName(name) {}
val overriddenSet = mutableSetOf<IrSimpleFunctionSymbol>()
scope.processOverriddenFunctionsFromSuperClasses(symbol, containingClass) {
if (it.fir.visibility == Visibilities.Private) {
return@processOverriddenFunctionsFromSuperClasses ProcessorAction.NEXT
}
processOverriddenFunctionSymbols(containingClass, session, scopeSession) {
for (overridden in fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(it, superClasses)) {
overriddenSet += overridden
}
ProcessorAction.NEXT
}
return overriddenSet.toList()
@@ -353,6 +363,27 @@ private fun FirClass.getSuperTypesAsIrClasses(
return irClass.superTypes.mapNotNull { it.classifierOrNull?.owner as? IrClass }.toSet()
}
internal fun FirProperty.processOverriddenPropertySymbols(
containingClass: FirClass,
session: FirSession,
scopeSession: ScopeSession,
processor: (FirPropertySymbol) -> Unit
): List<IrPropertySymbol> {
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
scope.processPropertiesByName(name) {}
val overriddenSet = mutableSetOf<IrPropertySymbol>()
scope.processOverriddenPropertiesFromSuperClasses(symbol, containingClass) {
if (it.fir.visibility == Visibilities.Private) {
return@processOverriddenPropertiesFromSuperClasses ProcessorAction.NEXT
}
processor(it)
ProcessorAction.NEXT
}
return overriddenSet.toList()
}
internal fun FirProperty.generateOverriddenPropertySymbols(
containingClass: FirClass,
session: FirSession,
@@ -361,20 +392,12 @@ internal fun FirProperty.generateOverriddenPropertySymbols(
fakeOverrideGenerator: FakeOverrideGenerator,
): List<IrPropertySymbol> {
val superClasses = containingClass.getSuperTypesAsIrClasses(declarationStorage) ?: return emptyList()
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
scope.processPropertiesByName(name) {}
val overriddenSet = mutableSetOf<IrPropertySymbol>()
scope.processOverriddenPropertiesFromSuperClasses(symbol, containingClass) {
if (it.fir.visibility == Visibilities.Private) {
return@processOverriddenPropertiesFromSuperClasses ProcessorAction.NEXT
}
processOverriddenPropertySymbols(containingClass, session, scopeSession) {
for (overridden in fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(it, superClasses)) {
overriddenSet += overridden
}
ProcessorAction.NEXT
}
return overriddenSet.toList()
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.generators.AnnotationGenerator
import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator
import org.jetbrains.kotlin.fir.backend.generators.DelegatedMemberGenerator
import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.ir.IrBuiltIns
@@ -35,4 +36,5 @@ interface Fir2IrComponents {
val annotationGenerator: AnnotationGenerator
val callGenerator: CallAndReferenceGenerator
val fakeOverrideGenerator: FakeOverrideGenerator
val delegatedMemberGenerator: DelegatedMemberGenerator
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.generators.AnnotationGenerator
import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator
import org.jetbrains.kotlin.fir.backend.generators.DelegatedMemberGenerator
import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer
@@ -35,6 +36,7 @@ class Fir2IrComponentsStorage(
override lateinit var annotationGenerator: AnnotationGenerator
override lateinit var callGenerator: CallAndReferenceGenerator
override lateinit var fakeOverrideGenerator: FakeOverrideGenerator
override lateinit var delegatedMemberGenerator: DelegatedMemberGenerator
override val lock: IrLock
get() = symbolTable.lock
@@ -9,10 +9,7 @@ import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.evaluate.evaluateConstants
import org.jetbrains.kotlin.fir.backend.generators.AnnotationGenerator
import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator
import org.jetbrains.kotlin.fir.backend.generators.DataClassMembersGenerator
import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator
import org.jetbrains.kotlin.fir.backend.generators.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic
@@ -270,6 +267,7 @@ class Fir2IrConverter(
val components = Fir2IrComponentsStorage(session, scopeSession, symbolTable, irFactory, signatureComposer)
val classifierStorage = Fir2IrClassifierStorage(components)
components.classifierStorage = classifierStorage
components.delegatedMemberGenerator = DelegatedMemberGenerator(components)
val declarationStorage = Fir2IrDeclarationStorage(components, moduleDescriptor)
components.declarationStorage = declarationStorage
components.visibilityConverter = visibilityConverter
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.builtins.StandardNames.BUILT_INS_PACKAGE_FQ_NAMES
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.backend.generators.DelegatedMemberGenerator
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
@@ -104,8 +103,6 @@ class Fir2IrDeclarationStorage(
private val localStorage by threadLocal { Fir2IrLocalStorage() }
private val delegatedMemberGenerator = DelegatedMemberGenerator(components)
private fun areCompatible(firFunction: FirFunction, irFunction: IrFunction): Boolean {
if (firFunction is FirSimpleFunction && irFunction is IrSimpleFunction) {
if (irFunction.name != firFunction.name) return false
@@ -891,7 +888,7 @@ class Fir2IrDeclarationStorage(
fun createIrFieldAndDelegatedMembers(field: FirField, owner: FirClass, irClass: IrClass): IrField {
val irField = createIrField(field, origin = IrDeclarationOrigin.DELEGATE)
irField.setAndModifyParent(irClass)
delegatedMemberGenerator.generate(irField, field, owner, irClass)
components.delegatedMemberGenerator.generate(irField, field, owner, irClass)
return irField
}
@@ -58,6 +58,8 @@ internal class ClassMemberGenerator(
}
}
fakeOverrideGenerator.bindOverriddenSymbols(irClass.declarations)
components.delegatedMemberGenerator.bindDelegatedMembersOverriddenSymbols(irClass)
klass.declarations.forEach { declaration ->
when {
declaration is FirTypeAlias -> {
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.scopes.processAllProperties
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
@@ -21,6 +22,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.isNothing
import org.jetbrains.kotlin.ir.types.isUnit
@@ -31,10 +33,13 @@ import org.jetbrains.kotlin.ir.types.isUnit
* methods and properties in the super-interface, and creates corresponding members in the subclass.
* TODO: generic super interface types and generic delegated members.
*/
internal class DelegatedMemberGenerator(
class DelegatedMemberGenerator(
private val components: Fir2IrComponents
) : Fir2IrComponents by components {
private val baseFunctionSymbols = mutableMapOf<IrFunction, List<FirNamedFunctionSymbol>>()
private val basePropertySymbols = mutableMapOf<IrProperty, List<FirPropertySymbol>>()
// Generate delegated members for [subClass]. The synthetic field [irField] has the super interface type.
fun generate(irField: IrField, firField: FirField, firSubClass: FirClass, subClass: IrClass) {
val subClassLookupTag = firSubClass.symbol.toLookupTag()
@@ -82,6 +87,28 @@ internal class DelegatedMemberGenerator(
}
}
fun bindDelegatedMembersOverriddenSymbols(irClass: IrClass) {
val superClasses by lazy(LazyThreadSafetyMode.NONE) {
irClass.superTypes.mapNotNullTo(mutableSetOf()) { it.classifierOrNull?.owner as? IrClass }
}
for (declaration in irClass.declarations) {
if (declaration.origin != IrDeclarationOrigin.DELEGATED_MEMBER) continue
when (declaration) {
is IrSimpleFunction -> {
declaration.overriddenSymbols = baseFunctionSymbols[declaration]?.flatMap {
fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(it, superClasses)
}?.filter { it.owner != declaration }.orEmpty()
}
is IrProperty -> {
declaration.overriddenSymbols = basePropertySymbols[declaration]?.flatMap {
fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(it, superClasses)
}?.filter { it.owner != declaration }.orEmpty()
}
else -> continue
}
}
}
private fun generateDelegatedFunction(
subClass: IrClass,
firSubClass: FirClass,
@@ -94,15 +121,13 @@ internal class DelegatedMemberGenerator(
delegateOverride, subClass, origin = IrDeclarationOrigin.DELEGATED_MEMBER,
containingClass = firSubClass.symbol.toLookupTag()
)
delegateFunction.overriddenSymbols =
delegateOverride.generateOverriddenFunctionSymbols(
firSubClass,
session,
scopeSession,
declarationStorage,
fakeOverrideGenerator
)
.filter { it.owner != delegateFunction }
val baseSymbols = mutableListOf<FirNamedFunctionSymbol>()
// the overridden symbols should be collected only after all fake overrides for all superclases are created and bound to their
// overridden symbols, otherwise in some cases they will be left in inconsistent state leading to the errors in IR
delegateOverride.processOverriddenFunctionSymbols(firSubClass, session, scopeSession) {
baseSymbols.add(it)
}
baseFunctionSymbols[delegateFunction] = baseSymbols
annotationGenerator.generate(delegateFunction, delegateOverride)
val body = createDelegateBody(irField, delegateFunction, superFunction)
@@ -166,14 +191,13 @@ internal class DelegatedMemberGenerator(
firDelegateProperty, subClass, origin = IrDeclarationOrigin.DELEGATED_MEMBER,
containingClass = firSubClass.symbol.toLookupTag()
)
delegateProperty.overriddenSymbols =
firDelegateProperty.generateOverriddenPropertySymbols(
firSubClass,
session,
scopeSession,
declarationStorage,
fakeOverrideGenerator
)
// the overridden symbols should be collected only after all fake overrides for all superclases are created and bound to their
// overridden symbols, otherwise in some cases they will be left in inconsistent state leading to the errors in IR
val baseSymbols = mutableListOf<FirPropertySymbol>()
firDelegateProperty.processOverriddenPropertySymbols(firSubClass, session, scopeSession) {
baseSymbols.add(it)
}
basePropertySymbols[delegateProperty] = baseSymbols
annotationGenerator.generate(delegateProperty, firDelegateProperty)
delegateProperty.getter!!.body = createDelegateBody(irField, delegateProperty.getter!!, superProperty.getter!!)