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 {