From 76ff71709112e70d000f9639dc9172ac49bdff16 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 14 Feb 2022 16:29:14 +0300 Subject: [PATCH] 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). --- .../fir/backend/Fir2IrDeclarationStorage.kt | 107 +++++++++++------- .../generators/FakeOverrideGenerator.kt | 4 +- .../removeAtBridgeToJavaDefault.kt | 6 - .../removeAtBridgeToJavaSuperClass.kt | 6 - .../superCallToRemoveAtInJavaDefault.kt | 3 - 5 files changed, 72 insertions(+), 54 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index 0bc49f6e8c1..efbdacc40cd 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -476,6 +476,11 @@ class Fir2IrDeclarationStorage( function.origin == FirDeclarationOrigin.Enhancement -> IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB 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) val name = simpleFunction?.name ?: if (isLambda) SpecialNames.ANONYMOUS else Name.special("") @@ -483,7 +488,6 @@ class Fir2IrDeclarationStorage( val isSuspend = if (isLambda) ((function as FirAnonymousFunction).typeRef as? FirResolvedTypeRef)?.type?.isSuspendFunctionType(session) == true else simpleFunction?.isSuspend == true - val signature = if (isLocal) null else signatureComposer.composeSignature(function, containingClass) val created = function.convertWithOffsets { startOffset, endOffset -> val result = declareIrSimpleFunction(signature, simpleFunction?.containerSource) { symbol -> irFactory.createFunction( @@ -792,13 +796,17 @@ class Fir2IrDeclarationStorage( containingClass: ConeClassLikeLookupTag? = null, ): IrProperty = convertCatching(property) { 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) if (property.delegate != null) { ((property.delegate as? FirQualifiedAccess)?.calleeReference?.resolvedSymbol?.fir as? FirTypeParameterRefsOwner)?.let { classifierStorage.preCacheTypeParameters(it) } } - val signature = if (isLocal) null else signatureComposer.composeSignature(property, containingClass) return property.convertWithOffsets { startOffset, endOffset -> val result = declareIrProperty(signature, property.containerSource) { symbol -> irFactory.createProperty( @@ -1181,27 +1189,11 @@ class Fir2IrDeclarationStorage( firFunctionSymbol, dispatchReceiverLookupTag, getCachedIrDeclaration = ::getCachedIrFunction, - createIrDeclaration = { parent, origin -> createIrFunction(fir, parent, predefinedOrigin = origin) }, + createIrDeclaration = { parent, origin -> + createIrFunction(fir, parent, predefinedOrigin = origin) + }, createIrLazyDeclaration = { signature, lazyParent, declarationOrigin -> - val symbol = Fir2IrSimpleFunctionSymbol(signature, fir.containerSource) - 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 + createIrLazyFunction(fir, signature, lazyParent, declarationOrigin) } ) as IrFunctionSymbol 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( firPropertySymbol: FirPropertySymbol, dispatchReceiverLookupTag: ConeClassLikeLookupTag? = null @@ -1238,22 +1257,7 @@ class Fir2IrDeclarationStorage( getCachedIrDeclaration = ::getCachedIrProperty, createIrDeclaration = { parent, origin -> createIrProperty(fir, parent, predefinedOrigin = origin) }, createIrLazyDeclaration = { signature, lazyParent, declarationOrigin -> - val symbol = Fir2IrPropertySymbol(signature, fir.containerSource) - 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 + createIrLazyProperty(fir, signature, lazyParent, declarationOrigin) } ) @@ -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 > ConeClassLookupTagWithFixedSymbol.findIrFakeOverride( name: Name, originalDeclaration: IrOverridableDeclaration ): IrSymbol? { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt index 4c4fd97cc4b..2fa08066943 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt @@ -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.isLocal 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.toSymbol import org.jetbrains.kotlin.fir.scopes.FirTypeScope @@ -75,7 +77,7 @@ class FakeOverrideGenerator( ) } - fun IrClass.getFakeOverrides(klass: FirClass, realDeclarations: Collection): List { + private fun IrClass.getFakeOverrides(klass: FirClass, realDeclarations: Collection): List { val result = mutableListOf() val useSiteMemberScope = klass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true) val superTypesCallableNames = useSiteMemberScope.getCallableNames() diff --git a/compiler/testData/codegen/box/builtinStubMethods/extendJavaClasses/removeAtBridgeToJavaDefault.kt b/compiler/testData/codegen/box/builtinStubMethods/extendJavaClasses/removeAtBridgeToJavaDefault.kt index 91cdb781976..d7b6ebfaa9d 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/extendJavaClasses/removeAtBridgeToJavaDefault.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/extendJavaClasses/removeAtBridgeToJavaDefault.kt @@ -3,12 +3,6 @@ // SKIP_JDK6 // 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 class Test : IntArrayList() diff --git a/compiler/testData/codegen/box/builtinStubMethods/extendJavaClasses/removeAtBridgeToJavaSuperClass.kt b/compiler/testData/codegen/box/builtinStubMethods/extendJavaClasses/removeAtBridgeToJavaSuperClass.kt index 779e5544167..34aeab98166 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/extendJavaClasses/removeAtBridgeToJavaSuperClass.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/extendJavaClasses/removeAtBridgeToJavaSuperClass.kt @@ -3,12 +3,6 @@ // SKIP_JDK6 // 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 class Test : IntArrayList() diff --git a/compiler/testData/codegen/box/builtinStubMethods/extendJavaClasses/superCallToRemoveAtInJavaDefault.kt b/compiler/testData/codegen/box/builtinStubMethods/extendJavaClasses/superCallToRemoveAtInJavaDefault.kt index 21a5ee5bd75..d4330d6d943 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/extendJavaClasses/superCallToRemoveAtInJavaDefault.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/extendJavaClasses/superCallToRemoveAtInJavaDefault.kt @@ -3,9 +3,6 @@ // SKIP_JDK6 // FULL_JDK -// IGNORE_BACKEND_FIR: JVM_IR -// FIR_STATUS: java.lang.NoSuchMethodError: IntArrayList.removeAt(I)Ljava/lang/Integer; - // FILE: superCallToRemoveAtInJavaDefault.kt class Test : IntArrayList() { override fun removeAt(index: Int): Int {