[FIR2IR] Generate fake overrides earlier and bind them later
Before this commit, we generated fake overrides at last FIR2IR stage, after having all functions and classes built. This could lead to a situation when fake override was called before it was generated. This commit fixes this situation.
This commit is contained in:
@@ -10,6 +10,7 @@ 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.declarations.*
|
||||
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
|
||||
@@ -23,6 +24,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedDeclarationDescriptor
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
|
||||
@@ -89,40 +91,90 @@ class Fir2IrConverter(
|
||||
it, irClass, isLocal = true
|
||||
)
|
||||
}
|
||||
val processedCallableNames = mutableSetOf<Name>()
|
||||
for (declaration in sortBySynthetic(anonymousObject.declarations)) {
|
||||
if (declaration is FirRegularClass) {
|
||||
registerClassAndNestedClasses(declaration, irClass)
|
||||
processClassAndNestedClassHeaders(declaration)
|
||||
}
|
||||
val irDeclaration = processMemberDeclaration(declaration, anonymousObject, irClass) ?: continue
|
||||
when (declaration) {
|
||||
is FirSimpleFunction -> processedCallableNames += declaration.name
|
||||
is FirProperty -> processedCallableNames += declaration.name
|
||||
}
|
||||
irClass.declarations += irDeclaration
|
||||
}
|
||||
return irClass
|
||||
}
|
||||
// Add delegated members *before* fake override generations.
|
||||
// Otherwise, fake overrides for delegated members, which are redundant, will be added.
|
||||
processedCallableNames += delegatedMemberNames(irClass)
|
||||
with(fakeOverrideGenerator) {
|
||||
irClass.addFakeOverrides(anonymousObject, processedCallableNames)
|
||||
}
|
||||
|
||||
// Sort declarations so that all non-synthetic declarations are before synthetic ones.
|
||||
// This is needed because converting synthetic fields for implementation delegation needs to know
|
||||
// existing declarations in the class to avoid adding redundant delegated members.
|
||||
private fun sortBySynthetic(declarations: List<FirDeclaration>) : Iterable<FirDeclaration> {
|
||||
return declarations.sortedBy { it.isSynthetic }
|
||||
return irClass
|
||||
}
|
||||
|
||||
private fun processClassMembers(
|
||||
regularClass: FirRegularClass,
|
||||
irClass: IrClass = classifierStorage.getCachedIrClass(regularClass)!!
|
||||
): IrClass {
|
||||
regularClass.getPrimaryConstructorIfAny()?.let {
|
||||
irClass.declarations += declarationStorage.createIrConstructor(
|
||||
it, irClass, isLocal = regularClass.isLocal
|
||||
)
|
||||
val irConstructor = regularClass.getPrimaryConstructorIfAny()?.let {
|
||||
declarationStorage.createIrConstructor(it, irClass, isLocal = regularClass.isLocal)
|
||||
}
|
||||
if (irConstructor != null) {
|
||||
irClass.declarations += irConstructor
|
||||
}
|
||||
val processedCallableNames = mutableSetOf<Name>()
|
||||
for (declaration in sortBySynthetic(regularClass.declarations)) {
|
||||
val irDeclaration = processMemberDeclaration(declaration, regularClass, irClass) ?: continue
|
||||
when (declaration) {
|
||||
is FirSimpleFunction -> processedCallableNames += declaration.name
|
||||
is FirProperty -> processedCallableNames += declaration.name
|
||||
}
|
||||
irClass.declarations += irDeclaration
|
||||
}
|
||||
// Add delegated members *before* fake override generations.
|
||||
// Otherwise, fake overrides for delegated members, which are redundant, will be added.
|
||||
processedCallableNames += delegatedMemberNames(irClass)
|
||||
// Add synthetic members *before* fake override generations.
|
||||
// Otherwise, redundant members, e.g., synthetic toString _and_ fake override toString, will be added.
|
||||
if (irConstructor != null && (irClass.isInline || irClass.isData)) {
|
||||
declarationStorage.enterScope(irConstructor)
|
||||
val dataClassMembersGenerator = DataClassMembersGenerator(components)
|
||||
if (irClass.isInline) {
|
||||
processedCallableNames += dataClassMembersGenerator.generateInlineClassMembers(regularClass, irClass)
|
||||
}
|
||||
if (irClass.isData) {
|
||||
processedCallableNames += dataClassMembersGenerator.generateDataClassMembers(regularClass, irClass)
|
||||
}
|
||||
declarationStorage.leaveScope(irConstructor)
|
||||
}
|
||||
with(fakeOverrideGenerator) {
|
||||
irClass.addFakeOverrides(regularClass, processedCallableNames)
|
||||
}
|
||||
|
||||
return irClass
|
||||
}
|
||||
|
||||
private fun delegatedMemberNames(irClass: IrClass): List<Name> {
|
||||
return irClass.declarations.filter {
|
||||
it.origin == IrDeclarationOrigin.DELEGATED_MEMBER
|
||||
}.mapNotNull {
|
||||
when (it) {
|
||||
is IrSimpleFunction -> it.name
|
||||
is IrProperty -> it.name
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort declarations so that all non-synthetic declarations are before synthetic ones.
|
||||
// This is needed because converting synthetic fields for implementation delegation needs to know
|
||||
// existing declarations in the class to avoid adding redundant delegated members.
|
||||
private fun sortBySynthetic(declarations: List<FirDeclaration>): Iterable<FirDeclaration> {
|
||||
return declarations.sortedBy { it.isSynthetic }
|
||||
}
|
||||
|
||||
private fun registerClassAndNestedClasses(regularClass: FirRegularClass, parent: IrDeclarationParent): IrClass {
|
||||
val irClass = classifierStorage.registerIrClass(regularClass, parent)
|
||||
regularClass.declarations.forEach {
|
||||
|
||||
+1
-32
@@ -15,19 +15,13 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenProperties
|
||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.unwrapSubstitutionOverrides
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.constructedClassType
|
||||
import org.jetbrains.kotlin.ir.util.isAnnotationClass
|
||||
@@ -61,32 +55,7 @@ internal class ClassMemberGenerator(
|
||||
convertFunctionContent(irPrimaryConstructor, primaryConstructor, containingClass = klass)
|
||||
}
|
||||
}
|
||||
val processedCallableNames = klass.declarations.mapNotNullTo(mutableSetOf()) {
|
||||
when (it) {
|
||||
is FirSimpleFunction -> it.name
|
||||
is FirProperty -> it.name
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
// Add delegated members *before* fake override generations.
|
||||
// Otherwise, fake overrides for delegated members, which are redundant, will be added.
|
||||
irClass.declarations.filter {
|
||||
it.origin == IrDeclarationOrigin.DELEGATED_MEMBER
|
||||
}.forEach {
|
||||
when (it) {
|
||||
is IrSimpleFunction -> processedCallableNames += it.name
|
||||
is IrProperty -> processedCallableNames += it.name
|
||||
}
|
||||
}
|
||||
// Add synthetic members *before* fake override generations.
|
||||
// Otherwise, redundant members, e.g., synthetic toString _and_ fake override toString, will be added.
|
||||
if (irClass.isInline && klass.getPrimaryConstructorIfAny() != null) {
|
||||
processedCallableNames += DataClassMembersGenerator(components).generateInlineClassMembers(klass, irClass)
|
||||
}
|
||||
if (irClass.isData && klass.getPrimaryConstructorIfAny() != null) {
|
||||
processedCallableNames += DataClassMembersGenerator(components).generateDataClassMembers(klass, irClass)
|
||||
}
|
||||
with(fakeOverrideGenerator) { irClass.addFakeOverrides(klass, processedCallableNames) }
|
||||
fakeOverrideGenerator.bindOverriddenSymbols(irClass.declarations)
|
||||
klass.declarations.forEach { declaration ->
|
||||
when {
|
||||
declaration is FirTypeAlias -> {
|
||||
|
||||
+35
-18
@@ -33,6 +33,9 @@ class FakeOverrideGenerator(
|
||||
private val fakeOverrideMode: FakeOverrideMode
|
||||
) {
|
||||
|
||||
private val baseFunctionSymbols = mutableMapOf<IrFunction, FirNamedFunctionSymbol>()
|
||||
private val basePropertySymbols = mutableMapOf<IrProperty, FirPropertySymbol>()
|
||||
|
||||
private fun IrSimpleFunction.withFunction(f: IrSimpleFunction.() -> Unit): IrSimpleFunction {
|
||||
return conversionScope.withFunction(this, f)
|
||||
}
|
||||
@@ -98,11 +101,9 @@ class FakeOverrideGenerator(
|
||||
// In fake overrides, parent logic is a bit specific, because
|
||||
// parent of *original* function (base class) is used for dispatch receiver,
|
||||
// but fake override itself uses parent from its containing (derived) class
|
||||
val overriddenSymbol = declarationStorage.getIrFunctionSymbol(baseSymbol) as IrSimpleFunctionSymbol
|
||||
irFunction.parent = this
|
||||
result += irFunction.withFunction {
|
||||
overriddenSymbols = listOf(overriddenSymbol)
|
||||
}
|
||||
baseFunctionSymbols[irFunction] = baseSymbol
|
||||
result += irFunction
|
||||
} else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalFunction.allowsToHaveFakeOverrideIn(klass)) {
|
||||
// Trivial fake override case
|
||||
val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideFunction(
|
||||
@@ -123,11 +124,9 @@ class FakeOverrideGenerator(
|
||||
if (irFunction.returnType.containsErrorType() || irFunction.valueParameters.any { it.type.containsErrorType() }) {
|
||||
return@processFunctionsByName
|
||||
}
|
||||
val overriddenSymbol = declarationStorage.getIrFunctionSymbol(baseSymbol) as IrSimpleFunctionSymbol
|
||||
irFunction.parent = this
|
||||
result += irFunction.withFunction {
|
||||
overriddenSymbols = listOf(overriddenSymbol)
|
||||
}
|
||||
baseFunctionSymbols[irFunction] = baseSymbol
|
||||
result += irFunction
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,10 +148,8 @@ class FakeOverrideGenerator(
|
||||
isLocal = isLocal
|
||||
)
|
||||
irProperty.parent = this
|
||||
result += irProperty.withProperty {
|
||||
discardAccessorsAccordingToBaseVisibility(baseSymbol)
|
||||
setOverriddenSymbolsForAccessors(declarationStorage, originalProperty, firOverriddenSymbol = baseSymbol)
|
||||
}
|
||||
basePropertySymbols[irProperty] = baseSymbol
|
||||
result += irProperty
|
||||
} else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalProperty.allowsToHaveFakeOverrideIn(klass)) {
|
||||
// Trivial fake override case
|
||||
val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideProperty(
|
||||
@@ -175,10 +172,8 @@ class FakeOverrideGenerator(
|
||||
return@processPropertiesByName
|
||||
}
|
||||
irProperty.parent = this
|
||||
result += irProperty.withProperty {
|
||||
discardAccessorsAccordingToBaseVisibility(baseSymbol)
|
||||
setOverriddenSymbolsForAccessors(declarationStorage, fakeOverrideProperty, firOverriddenSymbol = baseSymbol)
|
||||
}
|
||||
basePropertySymbols[irProperty] = baseSymbol
|
||||
result += irProperty
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,6 +181,28 @@ class FakeOverrideGenerator(
|
||||
return result
|
||||
}
|
||||
|
||||
fun bindOverriddenSymbols(declarations: List<IrDeclaration>) {
|
||||
for (declaration in declarations) {
|
||||
if (declaration.origin != IrDeclarationOrigin.FAKE_OVERRIDE) continue
|
||||
when (declaration) {
|
||||
is IrSimpleFunction -> {
|
||||
val baseSymbol = baseFunctionSymbols[declaration]!!
|
||||
val overriddenSymbol = declarationStorage.getIrFunctionSymbol(baseSymbol) as IrSimpleFunctionSymbol
|
||||
declaration.withFunction {
|
||||
overriddenSymbols = listOf(overriddenSymbol)
|
||||
}
|
||||
}
|
||||
is IrProperty -> {
|
||||
val baseSymbol = basePropertySymbols[declaration]!!
|
||||
declaration.withProperty {
|
||||
discardAccessorsAccordingToBaseVisibility(baseSymbol)
|
||||
setOverriddenSymbolsForAccessors(declarationStorage, declaration.isVar, firOverriddenSymbol = baseSymbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrProperty.discardAccessorsAccordingToBaseVisibility(baseSymbol: FirPropertySymbol) {
|
||||
// Do not create fake overrides for accessors if not allowed to do so, e.g., private lateinit var.
|
||||
if (baseSymbol.fir.getter?.allowsToHaveFakeOverride != true) {
|
||||
@@ -199,7 +216,7 @@ class FakeOverrideGenerator(
|
||||
|
||||
private fun IrProperty.setOverriddenSymbolsForAccessors(
|
||||
declarationStorage: Fir2IrDeclarationStorage,
|
||||
property: FirProperty,
|
||||
isVar: Boolean,
|
||||
firOverriddenSymbol: FirPropertySymbol
|
||||
): IrProperty {
|
||||
val irSymbol = declarationStorage.getIrPropertyOrFieldSymbol(firOverriddenSymbol) as? IrPropertySymbol ?: return this
|
||||
@@ -207,7 +224,7 @@ class FakeOverrideGenerator(
|
||||
getter?.apply {
|
||||
overriddenProperty.getter?.symbol?.let { overriddenSymbols = listOf(it) }
|
||||
}
|
||||
if (property.isVar) {
|
||||
if (isVar) {
|
||||
setter?.apply {
|
||||
overriddenProperty.setter?.symbol?.let { overriddenSymbols = listOf(it) }
|
||||
}
|
||||
|
||||
@@ -164,7 +164,9 @@ class Fir2IrLazyClass(
|
||||
}
|
||||
}
|
||||
with(fakeOverrideGenerator) {
|
||||
result += getFakeOverrides(fir, processedNames)
|
||||
val fakeOverrides = getFakeOverrides(fir, processedNames)
|
||||
bindOverriddenSymbols(fakeOverrides)
|
||||
result += fakeOverrides
|
||||
}
|
||||
// TODO: remove this check to save time
|
||||
for (declaration in result) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box() = Class().printSome()
|
||||
|
||||
public abstract class AbstractClass<T> {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// See also kt33054.kt
|
||||
|
||||
Reference in New Issue
Block a user