From 3c0f153de49abd4f9ac7581f09e3f4459c17073b Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Fri, 3 Nov 2023 13:56:03 +0200 Subject: [PATCH] [FIR2IR] Manage function symbols in declaration storage instead of declaration generator This is needed to be able to implement creation of unbound symbols for references of corresponding declarations (KT-62856) There was an exception from FIR2IR that was fixed with this change, so fir2ir test expectDeclarationWithWeakIncompatibilities started to pass along with IrActualizer, which reported some new errors --- .../fir/backend/Fir2IrDeclarationStorage.kt | 13 +++ .../generators/DataClassMembersGenerator.kt | 52 +++++----- .../Fir2IrCallableDeclarationsGenerator.kt | 94 ++++++++----------- .../Fir2IrLazyDeclarationsGenerator.kt | 23 ++--- ...eclarationWithWeakIncompatibilities.fir.kt | 8 +- 5 files changed, 90 insertions(+), 100 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 51878d455f6..db82cb9647e 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 @@ -38,6 +38,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl import org.jetbrains.kotlin.ir.expressions.IrSyntheticBodyKind import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.classId import org.jetbrains.kotlin.ir.util.createParameterDeclarations @@ -312,9 +313,14 @@ class Fir2IrDeclarationStorage( isLocal: Boolean = false, fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null ): IrSimpleFunction { + val signature = runIf(!isLocal && configuration.linkViaSignatures) { + signatureComposer.composeSignature(function, fakeOverrideOwnerLookupTag) + } + val irFunction = callablesGenerator.createIrFunction( function, irParent, + createFunctionSymbol(signature), predefinedOrigin, isLocal = isLocal, fakeOverrideOwnerLookupTag = fakeOverrideOwnerLookupTag @@ -324,6 +330,13 @@ class Fir2IrDeclarationStorage( return irFunction } + internal fun createFunctionSymbol(signature: IdSignature?): IrSimpleFunctionSymbol { + return when { + signature != null -> symbolTable.referenceSimpleFunction(signature) + else -> IrSimpleFunctionSymbolImpl() + } + } + private fun cacheIrFunction(function: FirFunction, irFunction: IrSimpleFunction, fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?) { when { irFunction.visibility == DescriptorVisibilities.LOCAL -> { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DataClassMembersGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DataClassMembersGenerator.kt index 363187a5bca..8f7ee3c1f52 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DataClassMembersGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DataClassMembersGenerator.kt @@ -307,34 +307,32 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) : Fir2IrCompon isOperator: Boolean = false, ): IrSimpleFunction { val signature = if (klass.symbol.classId.isLocal) null else components.signatureComposer.composeSignature(syntheticCounterpart) - return components.callablesGenerator.declareIrSimpleFunction(signature) { symbol -> - components.irFactory.createSimpleFunction( - startOffset = UNDEFINED_OFFSET, - endOffset = UNDEFINED_OFFSET, - origin = origin, - name = name, - visibility = DescriptorVisibilities.PUBLIC, - isInline = false, - isExpect = false, - returnType = returnType, - modality = Modality.OPEN, - symbol = symbol, - isTailrec = false, - isSuspend = false, - isOperator = isOperator, - isInfix = false, - isExternal = false, - isFakeOverride = false, - ).apply { - if (otherParameterNeeded) { - val irValueParameter = createSyntheticIrParameter( - this, syntheticCounterpart.valueParameters.first().name, components.irBuiltIns.anyNType - ) - this.valueParameters = listOf(irValueParameter) - } - metadata = FirMetadataSource.Function(syntheticCounterpart) + val symbol = components.declarationStorage.createFunctionSymbol(signature) + return components.irFactory.createSimpleFunction( + startOffset = UNDEFINED_OFFSET, + endOffset = UNDEFINED_OFFSET, + origin = origin, + name = name, + visibility = DescriptorVisibilities.PUBLIC, + isInline = false, + isExpect = false, + returnType = returnType, + modality = Modality.OPEN, + symbol = symbol, + isTailrec = false, + isSuspend = false, + isOperator = isOperator, + isInfix = false, + isExternal = false, + isFakeOverride = false, + ).apply { + if (otherParameterNeeded) { + val irValueParameter = createSyntheticIrParameter( + this, syntheticCounterpart.valueParameters.first().name, components.irBuiltIns.anyNType + ) + this.valueParameters = listOf(irValueParameter) } - }.apply { + metadata = FirMetadataSource.Function(syntheticCounterpart) setParent(irClass) addDeclarationToParent(this, irClass) dispatchReceiverParameter = generateDispatchReceiverParameter(this) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt index 393bf8f98e5..883decc274d 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt @@ -84,6 +84,7 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi fun createIrFunction( function: FirFunction, irParent: IrDeclarationParent?, + symbol: IrSimpleFunctionSymbol, predefinedOrigin: IrDeclarationOrigin? = null, isLocal: Boolean = false, fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null, @@ -109,26 +110,9 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi fakeOverrideOwnerLookupTag ) } - val parentIsExternal = irParent.isExternalParent() - // We don't generate signatures for local classes - // We attempt to avoid signature generation for non-local classes, with the following exceptions: - // - special mode (generateSignatures) oriented on special backend modes - // - lazy classes (they still use signatures) - // - primitive types (they can be from built-ins and don't have FIR counterpart) - // - overrides and fake overrides (sometimes we perform "receiver replacement" in FIR2IR breaking FIR->IR relation, - // or FIR counterpart can be just created on the fly) - val signature = - runUnless( - isLocal || - !configuration.linkViaSignatures && !parentIsExternal && - function.dispatchReceiverType?.isPrimitive != true && function.containerSource == null && - updatedOrigin != IrDeclarationOrigin.FAKE_OVERRIDE && !function.isOverride - ) { - signatureComposer.composeSignature(function, fakeOverrideOwnerLookupTag) - } - if (parentIsExternal && signature != null) { + if (irParent.isExternalParent()) { // For private functions signature is null, fallback to non-lazy function - return lazyDeclarationsGenerator.createIrLazyFunction(function as FirSimpleFunction, signature, irParent!!, updatedOrigin) + return lazyDeclarationsGenerator.createIrLazyFunction(function as FirSimpleFunction, symbol, irParent!!, updatedOrigin) } val name = simpleFunction?.name ?: if (isLambda) SpecialNames.ANONYMOUS else SpecialNames.NO_NAME_PROVIDED @@ -138,44 +122,42 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi if (isLambda) ((function as FirAnonymousFunction).typeRef as? FirResolvedTypeRef)?.type?.isSuspendOrKSuspendFunctionType(session) == true else function.isSuspend val created = function.convertWithOffsets { startOffset, endOffset -> - declareIrSimpleFunction(signature) { symbol -> - classifierStorage.preCacheTypeParameters(function, symbol) - irFactory.createSimpleFunction( - startOffset = if (updatedOrigin == IrDeclarationOrigin.DELEGATED_MEMBER) SYNTHETIC_OFFSET else startOffset, - endOffset = if (updatedOrigin == IrDeclarationOrigin.DELEGATED_MEMBER) SYNTHETIC_OFFSET else endOffset, - origin = updatedOrigin, - name = name, - visibility = components.visibilityConverter.convertToDescriptorVisibility(visibility), - isInline = simpleFunction?.isInline == true, - isExpect = simpleFunction?.isExpect == true, - returnType = function.returnTypeRef.toIrType(), - modality = simpleFunction?.modality ?: Modality.FINAL, - symbol = symbol, - isTailrec = simpleFunction?.isTailRec == true, - isSuspend = isSuspend, - isOperator = simpleFunction?.isOperator == true, - isInfix = simpleFunction?.isInfix == true, - isExternal = simpleFunction?.isExternal == true, - containerSource = simpleFunction?.containerSource, - ).apply { - metadata = FirMetadataSource.Function(function) - declarationStorage.withScope(symbol) { - /* - * `isLocal = true` indicates that a function is local or member of a local class - * containingClassLookupTag allows to distinguish those two cases - */ - setParent(irParent) - if (!(isLocal && function.containingClassLookupTag() == null)) { - addDeclarationToParent(this, irParent) - } - declareParameters( - function, irParent, - dispatchReceiverType = computeDispatchReceiverType(this, simpleFunction, irParent), - isStatic = simpleFunction?.isStatic == true, - forSetter = false, - ) - convertAnnotationsForNonDeclaredMembers(function, origin) + classifierStorage.preCacheTypeParameters(function, symbol) + irFactory.createSimpleFunction( + startOffset = if (updatedOrigin == IrDeclarationOrigin.DELEGATED_MEMBER) SYNTHETIC_OFFSET else startOffset, + endOffset = if (updatedOrigin == IrDeclarationOrigin.DELEGATED_MEMBER) SYNTHETIC_OFFSET else endOffset, + origin = updatedOrigin, + name = name, + visibility = components.visibilityConverter.convertToDescriptorVisibility(visibility), + isInline = simpleFunction?.isInline == true, + isExpect = simpleFunction?.isExpect == true, + returnType = function.returnTypeRef.toIrType(), + modality = simpleFunction?.modality ?: Modality.FINAL, + symbol = symbol, + isTailrec = simpleFunction?.isTailRec == true, + isSuspend = isSuspend, + isOperator = simpleFunction?.isOperator == true, + isInfix = simpleFunction?.isInfix == true, + isExternal = simpleFunction?.isExternal == true, + containerSource = simpleFunction?.containerSource, + ).apply { + metadata = FirMetadataSource.Function(function) + declarationStorage.withScope(symbol) { + /* + * `isLocal = true` indicates that a function is local or member of a local class + * containingClassLookupTag allows to distinguish those two cases + */ + setParent(irParent) + if (!(isLocal && function.containingClassLookupTag() == null)) { + addDeclarationToParent(this, irParent) } + declareParameters( + function, irParent, + dispatchReceiverType = computeDispatchReceiverType(this, simpleFunction, irParent), + isStatic = simpleFunction?.isStatic == true, + forSetter = false, + ) + convertAnnotationsForNonDeclaredMembers(function, origin) } } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt index 4a1a3e5f97c..eacd4b2f939 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.lazy.* import org.jetbrains.kotlin.fir.resolve.providers.firProvider import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorPublicSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrFieldPublicSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrPropertyPublicSymbolImpl @@ -23,25 +24,21 @@ import org.jetbrains.kotlin.utils.addToStdlib.runIf class Fir2IrLazyDeclarationsGenerator(val components: Fir2IrComponents) : Fir2IrComponents by components { internal fun createIrLazyFunction( fir: FirSimpleFunction, - signature: IdSignature, + symbol: IrSimpleFunctionSymbol, lazyParent: IrDeclarationParent, declarationOrigin: IrDeclarationOrigin ): IrSimpleFunction { - val symbol = symbolTable.referenceSimpleFunction(signature) val irFunction = fir.convertWithOffsets { startOffset, endOffset -> - symbolTable.declareSimpleFunction(signature, { symbol }) { - val firContainingClass = (lazyParent as? Fir2IrLazyClass)?.fir - val isFakeOverride = fir.isFakeOverride(firContainingClass) - Fir2IrLazySimpleFunction( - components, startOffset, endOffset, declarationOrigin, - fir, firContainingClass, symbol, isFakeOverride - ).apply { - this.parent = lazyParent - } + val firContainingClass = (lazyParent as? Fir2IrLazyClass)?.fir + val isFakeOverride = fir.isFakeOverride(firContainingClass) + Fir2IrLazySimpleFunction( + components, startOffset, endOffset, declarationOrigin, + fir, firContainingClass, symbol, isFakeOverride + ).apply { + this.parent = lazyParent + prepareTypeParameters() } } - // NB: this is needed to prevent recursions in case of self bounds - (irFunction as Fir2IrLazySimpleFunction).prepareTypeParameters() return irFunction } diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectDeclarationWithWeakIncompatibilities.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectDeclarationWithWeakIncompatibilities.fir.kt index c632c74dc2c..2064b039f68 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectDeclarationWithWeakIncompatibilities.fir.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectDeclarationWithWeakIncompatibilities.fir.kt @@ -2,14 +2,14 @@ // MODULE: m1-common // FILE: common.kt -expect class Foo1 -expect class Foo2 +expect class Foo1 +expect class Foo2 expect fun foo2(): Int -expect val s: String +expect val s: String -expect open class Foo3 +expect open class Foo3 // MODULE: m2-jvm()()(m1-common)