FIR2IR: don't create non-lazy fake overrides inside lazy class

This commit allows to calculate member with initial signature properly.
Only lazy IR members are suitable to calculate initial signature.
Before this commit we sometimes built non-lazy children for lazy class.
Now we build lazy children (with an exception of private declarations).
This commit is contained in:
Mikhail Glukhikh
2022-02-14 16:29:14 +03:00
committed by Space
parent 80a68ec433
commit 76ff717091
5 changed files with 72 additions and 54 deletions
@@ -476,6 +476,11 @@ class Fir2IrDeclarationStorage(
function.origin == FirDeclarationOrigin.Enhancement -> IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB function.origin == FirDeclarationOrigin.Enhancement -> IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB
else -> function.computeIrOrigin(predefinedOrigin) else -> function.computeIrOrigin(predefinedOrigin)
} }
val signature = if (isLocal) null else signatureComposer.composeSignature(function, containingClass)
if (irParent is Fir2IrLazyClass && signature != null) {
// For private functions signature is null, fallback to non-lazy function
return createIrLazyFunction(function as FirSimpleFunction, signature, irParent, updatedOrigin)
}
classifierStorage.preCacheTypeParameters(function) classifierStorage.preCacheTypeParameters(function)
val name = simpleFunction?.name val name = simpleFunction?.name
?: if (isLambda) SpecialNames.ANONYMOUS else Name.special("<no name provided>") ?: if (isLambda) SpecialNames.ANONYMOUS else Name.special("<no name provided>")
@@ -483,7 +488,6 @@ class Fir2IrDeclarationStorage(
val isSuspend = val isSuspend =
if (isLambda) ((function as FirAnonymousFunction).typeRef as? FirResolvedTypeRef)?.type?.isSuspendFunctionType(session) == true if (isLambda) ((function as FirAnonymousFunction).typeRef as? FirResolvedTypeRef)?.type?.isSuspendFunctionType(session) == true
else simpleFunction?.isSuspend == true else simpleFunction?.isSuspend == true
val signature = if (isLocal) null else signatureComposer.composeSignature(function, containingClass)
val created = function.convertWithOffsets { startOffset, endOffset -> val created = function.convertWithOffsets { startOffset, endOffset ->
val result = declareIrSimpleFunction(signature, simpleFunction?.containerSource) { symbol -> val result = declareIrSimpleFunction(signature, simpleFunction?.containerSource) { symbol ->
irFactory.createFunction( irFactory.createFunction(
@@ -792,13 +796,17 @@ class Fir2IrDeclarationStorage(
containingClass: ConeClassLikeLookupTag? = null, containingClass: ConeClassLikeLookupTag? = null,
): IrProperty = convertCatching(property) { ): IrProperty = convertCatching(property) {
val origin = property.computeIrOrigin(predefinedOrigin) val origin = property.computeIrOrigin(predefinedOrigin)
val signature = if (isLocal) null else signatureComposer.composeSignature(property, containingClass)
if (irParent is Fir2IrLazyClass && signature != null) {
// For private functions signature is null, fallback to non-lazy property
return createIrLazyProperty(property, signature, irParent, origin)
}
classifierStorage.preCacheTypeParameters(property) classifierStorage.preCacheTypeParameters(property)
if (property.delegate != null) { if (property.delegate != null) {
((property.delegate as? FirQualifiedAccess)?.calleeReference?.resolvedSymbol?.fir as? FirTypeParameterRefsOwner)?.let { ((property.delegate as? FirQualifiedAccess)?.calleeReference?.resolvedSymbol?.fir as? FirTypeParameterRefsOwner)?.let {
classifierStorage.preCacheTypeParameters(it) classifierStorage.preCacheTypeParameters(it)
} }
} }
val signature = if (isLocal) null else signatureComposer.composeSignature(property, containingClass)
return property.convertWithOffsets { startOffset, endOffset -> return property.convertWithOffsets { startOffset, endOffset ->
val result = declareIrProperty(signature, property.containerSource) { symbol -> val result = declareIrProperty(signature, property.containerSource) { symbol ->
irFactory.createProperty( irFactory.createProperty(
@@ -1181,27 +1189,11 @@ class Fir2IrDeclarationStorage(
firFunctionSymbol, firFunctionSymbol,
dispatchReceiverLookupTag, dispatchReceiverLookupTag,
getCachedIrDeclaration = ::getCachedIrFunction, getCachedIrDeclaration = ::getCachedIrFunction,
createIrDeclaration = { parent, origin -> createIrFunction(fir, parent, predefinedOrigin = origin) }, createIrDeclaration = { parent, origin ->
createIrFunction(fir, parent, predefinedOrigin = origin)
},
createIrLazyDeclaration = { signature, lazyParent, declarationOrigin -> createIrLazyDeclaration = { signature, lazyParent, declarationOrigin ->
val symbol = Fir2IrSimpleFunctionSymbol(signature, fir.containerSource) createIrLazyFunction(fir, signature, lazyParent, declarationOrigin)
val irFunction = fir.convertWithOffsets { startOffset, endOffset ->
symbolTable.declareSimpleFunction(signature, { symbol }) {
val isFakeOverride =
firFunctionSymbol is FirNamedFunctionSymbol && fir.isSubstitutionOrIntersectionOverride &&
firFunctionSymbol.dispatchReceiverClassOrNull() !=
firFunctionSymbol.originalForSubstitutionOverride?.dispatchReceiverClassOrNull()
Fir2IrLazySimpleFunction(
components, startOffset, endOffset, declarationOrigin,
fir, lazyParent.fir, symbol, isFakeOverride
).apply {
this.parent = lazyParent
}
}
}
functionCache[fir] = irFunction
// NB: this is needed to prevent recursions in case of self bounds
(irFunction as Fir2IrLazySimpleFunction).prepareTypeParameters()
irFunction
} }
) as IrFunctionSymbol ) as IrFunctionSymbol
if (unmatchedReceiver && dispatchReceiverLookupTag is ConeClassLookupTagWithFixedSymbol) { if (unmatchedReceiver && dispatchReceiverLookupTag is ConeClassLookupTagWithFixedSymbol) {
@@ -1218,6 +1210,33 @@ class Fir2IrDeclarationStorage(
} }
} }
private fun createIrLazyFunction(
fir: FirSimpleFunction,
signature: IdSignature,
lazyParent: Fir2IrLazyClass,
declarationOrigin: IrDeclarationOrigin
): IrSimpleFunction {
val symbol = Fir2IrSimpleFunctionSymbol(signature, fir.containerSource)
val firFunctionSymbol = fir.symbol
val irFunction = fir.convertWithOffsets { startOffset, endOffset ->
symbolTable.declareSimpleFunction(signature, { symbol }) {
val isFakeOverride = fir.isSubstitutionOrIntersectionOverride &&
firFunctionSymbol.dispatchReceiverClassOrNull() !=
firFunctionSymbol.originalForSubstitutionOverride?.dispatchReceiverClassOrNull()
Fir2IrLazySimpleFunction(
components, startOffset, endOffset, declarationOrigin,
fir, lazyParent.fir, symbol, isFakeOverride
).apply {
this.parent = lazyParent
}
}
}
functionCache[fir] = irFunction
// NB: this is needed to prevent recursions in case of self bounds
(irFunction as Fir2IrLazySimpleFunction).prepareTypeParameters()
return irFunction
}
fun getIrPropertySymbol( fun getIrPropertySymbol(
firPropertySymbol: FirPropertySymbol, firPropertySymbol: FirPropertySymbol,
dispatchReceiverLookupTag: ConeClassLikeLookupTag? = null dispatchReceiverLookupTag: ConeClassLikeLookupTag? = null
@@ -1238,22 +1257,7 @@ class Fir2IrDeclarationStorage(
getCachedIrDeclaration = ::getCachedIrProperty, getCachedIrDeclaration = ::getCachedIrProperty,
createIrDeclaration = { parent, origin -> createIrProperty(fir, parent, predefinedOrigin = origin) }, createIrDeclaration = { parent, origin -> createIrProperty(fir, parent, predefinedOrigin = origin) },
createIrLazyDeclaration = { signature, lazyParent, declarationOrigin -> createIrLazyDeclaration = { signature, lazyParent, declarationOrigin ->
val symbol = Fir2IrPropertySymbol(signature, fir.containerSource) createIrLazyProperty(fir, signature, lazyParent, declarationOrigin)
val irProperty = fir.convertWithOffsets { startOffset, endOffset ->
symbolTable.declareProperty(signature, { symbol }) {
val isFakeOverride =
fir.isSubstitutionOrIntersectionOverride &&
firPropertySymbol.dispatchReceiverClassOrNull() !=
firPropertySymbol.originalForSubstitutionOverride?.dispatchReceiverClassOrNull()
Fir2IrLazyProperty(
components, startOffset, endOffset, declarationOrigin, fir, lazyParent.fir, symbol, isFakeOverride
).apply {
this.parent = lazyParent
}
}
}
propertyCache[fir] = irProperty
return symbol
} }
) )
@@ -1284,6 +1288,33 @@ class Fir2IrDeclarationStorage(
} }
} }
private fun createIrLazyProperty(
fir: FirProperty,
signature: IdSignature,
lazyParent: Fir2IrLazyClass,
declarationOrigin: IrDeclarationOrigin
): IrProperty {
val symbol = Fir2IrPropertySymbol(signature, fir.containerSource)
val firPropertySymbol = fir.symbol
val irProperty = fir.convertWithOffsets { startOffset, endOffset ->
symbolTable.declareProperty(signature, { symbol }) {
val isFakeOverride =
fir.isSubstitutionOrIntersectionOverride &&
firPropertySymbol.dispatchReceiverClassOrNull() !=
firPropertySymbol.originalForSubstitutionOverride?.dispatchReceiverClassOrNull()
Fir2IrLazyProperty(
components, startOffset, endOffset, declarationOrigin, fir, lazyParent.fir, symbol, isFakeOverride
).apply {
this.parent = lazyParent
}
}
}
propertyCache[fir] = irProperty
// NB: this is needed to prevent recursions in case of self bounds
(irProperty as Fir2IrLazyProperty).prepareTypeParameters()
return irProperty
}
private inline fun <reified S : IrSymbol, reified D : IrOverridableDeclaration<S>> ConeClassLookupTagWithFixedSymbol.findIrFakeOverride( private inline fun <reified S : IrSymbol, reified D : IrOverridableDeclaration<S>> ConeClassLookupTagWithFixedSymbol.findIrFakeOverride(
name: Name, originalDeclaration: IrOverridableDeclaration<S> name: Name, originalDeclaration: IrOverridableDeclaration<S>
): IrSymbol? { ): IrSymbol? {
@@ -16,6 +16,8 @@ import org.jetbrains.kotlin.fir.declarations.utils.allowsToHaveFakeOverride
import org.jetbrains.kotlin.fir.declarations.utils.isExpect import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.declarations.utils.isLocal import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.declarations.utils.visibility import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.FirTypeScope
@@ -75,7 +77,7 @@ class FakeOverrideGenerator(
) )
} }
fun IrClass.getFakeOverrides(klass: FirClass, realDeclarations: Collection<FirDeclaration>): List<IrDeclaration> { private fun IrClass.getFakeOverrides(klass: FirClass, realDeclarations: Collection<FirDeclaration>): List<IrDeclaration> {
val result = mutableListOf<IrDeclaration>() val result = mutableListOf<IrDeclaration>()
val useSiteMemberScope = klass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true) val useSiteMemberScope = klass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
val superTypesCallableNames = useSiteMemberScope.getCallableNames() val superTypesCallableNames = useSiteMemberScope.getCallableNames()
@@ -3,12 +3,6 @@
// SKIP_JDK6 // SKIP_JDK6
// FULL_JDK // FULL_JDK
// IGNORE_BACKEND_FIR: JVM_IR
// FIR_STATUS: java.lang.StackOverflowError
// at Test.remove(removeAtBridgeToJavaDefault.kt:7)
// at Test.remove(removeAtBridgeToJavaDefault.kt:7)
// at Test.remove(removeAtBridgeToJavaDefault.kt:7)
// FILE: removeAtBridgeToJavaDefault.kt // FILE: removeAtBridgeToJavaDefault.kt
class Test : IntArrayList() class Test : IntArrayList()
@@ -3,12 +3,6 @@
// SKIP_JDK6 // SKIP_JDK6
// FULL_JDK // FULL_JDK
// IGNORE_BACKEND_FIR: JVM_IR
// FIR_STATUS: java.lang.StackOverflowError
// at Test.remove(removeAtBridgeToJavaSuperClass.kt:7)
// at Test.remove(removeAtBridgeToJavaSuperClass.kt:7)
// at Test.remove(removeAtBridgeToJavaSuperClass.kt:7)
// FILE: removeAtBridgeToJavaSuperClass.kt // FILE: removeAtBridgeToJavaSuperClass.kt
class Test : IntArrayList() class Test : IntArrayList()
@@ -3,9 +3,6 @@
// SKIP_JDK6 // SKIP_JDK6
// FULL_JDK // FULL_JDK
// IGNORE_BACKEND_FIR: JVM_IR
// FIR_STATUS: java.lang.NoSuchMethodError: IntArrayList.removeAt(I)Ljava/lang/Integer;
// FILE: superCallToRemoveAtInJavaDefault.kt // FILE: superCallToRemoveAtInJavaDefault.kt
class Test : IntArrayList() { class Test : IntArrayList() {
override fun removeAt(index: Int): Int { override fun removeAt(index: Int): Int {