From 08ebe0448507c8b670da44dfd33e42f8ef550797 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Fri, 25 Aug 2023 13:49:03 +0300 Subject: [PATCH] [FIR2IR] Extract logic of IR declarations generation into separate component. Part 1 This commit just moves methods, which create IR callable declarations from Fir2IrDeclarationStorage to newly created Fir2IrCallableDeclarationsGenerator and Fir2IrLazyDeclarationsGenerator without any modifications. Code in generators contains some errors (mostly because it refers to the logic of caching created declaration), and those errors will be fixed in following commits --- .../kotlin/fir/backend/ConversionUtils.kt | 2 +- .../kotlin/fir/backend/Fir2IrComponents.kt | 8 +- .../fir/backend/Fir2IrComponentsStorage.kt | 13 +- .../kotlin/fir/backend/Fir2IrConverter.kt | 4 +- .../fir/backend/Fir2IrDeclarationStorage.kt | 1134 +---------------- .../kotlin/fir/backend/Fir2IrVisitor.kt | 20 +- .../generators/DataClassMembersGenerator.kt | 2 +- .../generators/DelegatedMemberGenerator.kt | 4 +- .../generators/FakeOverrideGenerator.kt | 6 +- .../Fir2IrCallableDeclarationsGenerator.kt | 1020 +++++++++++++++ .../Fir2IrLazyDeclarationsGenerator.kt | 98 ++ .../kotlin/fir/lazy/Fir2IrLazyConstructor.kt | 8 +- .../kotlin/fir/lazy/Fir2IrLazyProperty.kt | 24 +- .../fir/lazy/Fir2IrLazyPropertyAccessor.kt | 6 +- .../fir/lazy/Fir2IrLazySimpleFunction.kt | 6 +- 15 files changed, 1221 insertions(+), 1134 deletions(-) create mode 100644 compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt create mode 100644 compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt index 0cdb51befb5..b10bbd56376 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt @@ -583,7 +583,7 @@ fun Fir2IrComponents.createTemporaryVariable( conversionScope: Fir2IrConversionScope, nameHint: String? = null ): Pair { - val receiverVariable = declarationStorage.declareTemporaryVariable(receiverExpression, nameHint).apply { + val receiverVariable = callablesGenerator.declareTemporaryVariable(receiverExpression, nameHint).apply { parent = conversionScope.parentFromStack() } val variableSymbol = receiverVariable.symbol diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt index 902edb06314..18ca4e31152 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt @@ -6,10 +6,7 @@ package org.jetbrains.kotlin.fir.backend import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.backend.generators.AnnotationGenerator -import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator -import org.jetbrains.kotlin.fir.backend.generators.DelegatedMemberGenerator -import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator +import org.jetbrains.kotlin.fir.backend.generators.* import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer import org.jetbrains.kotlin.ir.IrLock @@ -37,6 +34,9 @@ interface Fir2IrComponents { val signatureComposer: FirBasedSignatureComposer val visibilityConverter: Fir2IrVisibilityConverter + val callablesGenerator: Fir2IrCallableDeclarationsGenerator + val lazyDeclarationsGenerator: Fir2IrLazyDeclarationsGenerator + val annotationGenerator: AnnotationGenerator val callGenerator: CallAndReferenceGenerator val fakeOverrideGenerator: FakeOverrideGenerator diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt index 214dbd8de69..dc2c5601a7e 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt @@ -6,10 +6,7 @@ package org.jetbrains.kotlin.fir.backend import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.backend.generators.AnnotationGenerator -import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator -import org.jetbrains.kotlin.fir.backend.generators.DelegatedMemberGenerator -import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator +import org.jetbrains.kotlin.fir.backend.generators.* import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer @@ -40,16 +37,20 @@ class Fir2IrComponentsStorage( override val classifierStorage: Fir2IrClassifierStorage = Fir2IrClassifierStorage(this, commonMemberStorage) override val declarationStorage: Fir2IrDeclarationStorage = Fir2IrDeclarationStorage(this, moduleDescriptor, commonMemberStorage) + override val callablesGenerator: Fir2IrCallableDeclarationsGenerator = Fir2IrCallableDeclarationsGenerator(this) + override val lazyDeclarationsGenerator: Fir2IrLazyDeclarationsGenerator = Fir2IrLazyDeclarationsGenerator(this) + + // builtins should go after storages and generators, because they use them during initialization override val irBuiltIns: IrBuiltInsOverFir = initializedIrBuiltIns ?: IrBuiltInsOverFir( this, configuration.languageVersionSettings, moduleDescriptor, irMangler ) - override val builtIns: Fir2IrBuiltIns = Fir2IrBuiltIns(this, specialSymbolProvider) + override val irProviders: List = listOf(FirIrProvider(this)) override val typeConverter: Fir2IrTypeConverter = Fir2IrTypeConverter(this) - private val conversionScope = Fir2IrConversionScope(configuration) + val fir2IrVisitor: Fir2IrVisitor = Fir2IrVisitor(this, conversionScope) override val annotationGenerator: AnnotationGenerator = AnnotationGenerator(this) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt index b4ed221addd..d865d087c7c 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt @@ -470,7 +470,7 @@ class Fir2IrConverter( } is FirField -> { if (declaration.isSynthetic) { - declarationStorage.createIrFieldAndDelegatedMembers(declaration, containingClass!!, parent as IrClass) + callablesGenerator.createIrFieldAndDelegatedMembers(declaration, containingClass!!, parent as IrClass) } else { throw AssertionError("Unexpected non-synthetic field: ${declaration::class}") } @@ -486,7 +486,7 @@ class Fir2IrConverter( classifierStorage.getIrEnumEntry(declaration, parent as IrClass) } is FirAnonymousInitializer -> { - declarationStorage.createIrAnonymousInitializer(declaration, parent as IrClass) + callablesGenerator.createIrAnonymousInitializer(declaration, parent as IrClass) } is FirTypeAlias -> { // DO NOTHING 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 b81808f6a4d..6b1691ae25e 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 @@ -5,70 +5,54 @@ package org.jetbrains.kotlin.fir.backend -import com.intellij.openapi.progress.ProcessCanceledException import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.builtins.StandardNames.BUILT_INS_PACKAGE_FQ_NAMES import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fir.* -import org.jetbrains.kotlin.fir.backend.generators.generateOverriddenAccessorSymbols import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.buildProperty -import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter -import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter -import org.jetbrains.kotlin.fir.declarations.utils.* +import org.jetbrains.kotlin.fir.declarations.utils.isExpect +import org.jetbrains.kotlin.fir.declarations.utils.isStatic +import org.jetbrains.kotlin.fir.declarations.utils.visibility import org.jetbrains.kotlin.fir.descriptors.FirBuiltInsPackageFragment import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor -import org.jetbrains.kotlin.fir.descriptors.FirPackageFragmentDescriptor -import org.jetbrains.kotlin.fir.expressions.FirConstExpression -import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression -import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyConstructor -import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty -import org.jetbrains.kotlin.fir.lazy.Fir2IrLazySimpleFunction -import org.jetbrains.kotlin.fir.references.toResolvedBaseSymbol import org.jetbrains.kotlin.fir.references.toResolvedValueParameterSymbol -import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isLocalClassOrAnonymousObject -import org.jetbrains.kotlin.fir.resolve.isKFunctionInvoke import org.jetbrains.kotlin.fir.resolve.providers.firProvider import org.jetbrains.kotlin.fir.resolve.toSymbol -import org.jetbrains.kotlin.fir.symbols.* +import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag +import org.jetbrains.kotlin.fir.symbols.Fir2IrConstructorSymbol +import org.jetbrains.kotlin.fir.symbols.Fir2IrScriptSymbol +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry -import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET -import org.jetbrains.kotlin.ir.builders.declarations.UNDEFINED_PARAMETER_INDEX import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin.GeneratedByPlugin -import org.jetbrains.kotlin.ir.declarations.impl.* +import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrScriptImpl +import org.jetbrains.kotlin.ir.declarations.impl.SCRIPT_K2_ORIGIN import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass -import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrSyntheticBodyKind -import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.symbols.impl.* +import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.load.kotlin.FacadeClassSource import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.name.NameUtils -import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.types.AbstractTypeChecker -import org.jetbrains.kotlin.utils.addToStdlib.runUnless -import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment import org.jetbrains.kotlin.utils.threadLocal import java.util.concurrent.ConcurrentHashMap -@OptIn(ObsoleteDescriptorBasedAPI::class) class Fir2IrDeclarationStorage( private val components: Fir2IrComponents, private val moduleDescriptor: FirModuleDescriptor, @@ -270,12 +254,6 @@ class Fir2IrDeclarationStorage( symbolTable.leaveScope(symbol) } - private fun FirTypeRef.toIrType(typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT): IrType = - with(typeConverter) { toIrType(typeOrigin) } - - private fun ConeKotlinType.toIrType(typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT): IrType = - with(typeConverter) { toIrType(typeOrigin) } - private fun getIrExternalOrBuiltInsPackageFragment(fqName: FqName, firOrigin: FirDeclarationOrigin): IrExternalPackageFragment { val isBuiltIn = fqName in BUILT_INS_PACKAGE_FQ_NAMES return if (isBuiltIn) getIrBuiltInsPackageFragment(fqName) else getIrExternalPackageFragment(fqName, firOrigin) @@ -283,7 +261,7 @@ class Fir2IrDeclarationStorage( private fun getIrBuiltInsPackageFragment(fqName: FqName): IrExternalPackageFragment { return builtInsFragmentCache.getOrPut(fqName) { - createExternalPackageFragment(FirBuiltInsPackageFragment(fqName, moduleDescriptor)) + callablesGenerator.createExternalPackageFragment(FirBuiltInsPackageFragment(fqName, moduleDescriptor)) } } @@ -293,8 +271,8 @@ class Fir2IrDeclarationStorage( ): IrExternalPackageFragment { val fragments = fragmentCache.getOrPut(fqName) { ExternalPackageFragments( - fragmentForDependencies = createExternalPackageFragment(fqName, FirModuleDescriptor(session, moduleDescriptor.builtIns)), - fragmentForPrecompiledBinaries = createExternalPackageFragment(fqName, moduleDescriptor) + fragmentForDependencies = callablesGenerator.createExternalPackageFragment(fqName, FirModuleDescriptor(session, moduleDescriptor.builtIns)), + fragmentForPrecompiledBinaries = callablesGenerator.createExternalPackageFragment(fqName, moduleDescriptor) ) } // Make sure that external package fragments have a different module descriptor. The module descriptors are compared @@ -306,15 +284,6 @@ class Fir2IrDeclarationStorage( } } - private fun createExternalPackageFragment(fqName: FqName, moduleDescriptor: FirModuleDescriptor): IrExternalPackageFragment { - return createExternalPackageFragment(FirPackageFragmentDescriptor(fqName, moduleDescriptor)) - } - - private fun createExternalPackageFragment(packageFragmentDescriptor: PackageFragmentDescriptor): IrExternalPackageFragment { - val symbol = IrExternalPackageFragmentSymbolImpl(packageFragmentDescriptor) - return IrExternalPackageFragmentImpl(symbol, packageFragmentDescriptor.fqName) - } - internal fun findIrParent( packageFqName: FqName, parentLookupTag: ConeClassLikeLookupTag?, @@ -381,7 +350,7 @@ class Fir2IrDeclarationStorage( return parentPackage } - private class NonCachedSourceFileFacadeClass( + internal class NonCachedSourceFileFacadeClass( origin: IrDeclarationOrigin, name: Name, source: SourceElement, @@ -403,51 +372,6 @@ class Fir2IrDeclarationStorage( override fun getContainingFile(): SourceFile = SourceFile.NO_SOURCE_FILE } - /** - * [firCallable] is function or property (if [irFunction] is a property accessor) for - * which [irFunction] was build - * - * It is needed to determine proper dispatch receiver type if this declaration is fake-override - */ - private fun computeDispatchReceiverType( - irFunction: IrSimpleFunction, - firCallable: FirCallableDeclaration?, - parent: IrDeclarationParent?, - ): IrType? { - /* - * If some function is not fake-override, then its type should be just - * default type of containing class - * For fake overrides the default type calculated in the following way: - * 1. Find first overridden function, which is not fake override - * 2. Take its containing class - * 3. Find supertype of current containing class with type constructor of - * class from step 2 - */ - if (firCallable is FirProperty && firCallable.isLocal) return null - val containingClass = computeContainingClass(parent) ?: return null - val defaultType = containingClass.defaultType - if (firCallable == null) return defaultType - if (irFunction.origin != IrDeclarationOrigin.FAKE_OVERRIDE) return defaultType - - val originalCallable = firCallable.unwrapFakeOverrides() - val containerOfOriginalCallable = originalCallable.containingClassLookupTag() ?: return defaultType - val containerOfFakeOverride = firCallable.dispatchReceiverType ?: return defaultType - val correspondingSupertype = AbstractTypeChecker.findCorrespondingSupertypes( - session.typeContext.newTypeCheckerState(errorTypesEqualToAnything = false, stubTypesEqualToAnything = false), - containerOfFakeOverride, - containerOfOriginalCallable - ).firstOrNull() as ConeKotlinType? ?: return defaultType - return correspondingSupertype.toIrType() - } - - private fun computeContainingClass(parent: IrDeclarationParent?): IrClass? { - return if (parent is IrClass && parent !is NonCachedSourceFileFacadeClass) { - parent - } else { - null - } - } - private fun findIrParent(callableDeclaration: FirCallableDeclaration): IrDeclarationParent? { val firBasedSymbol = callableDeclaration.symbol val callableId = firBasedSymbol.callableId @@ -455,151 +379,6 @@ class Fir2IrDeclarationStorage( return findIrParent(callableId.packageName, callableDeclaration.containingClassLookupTag(), firBasedSymbol, callableOrigin) } - private fun IrDeclaration.setAndModifyParent(irParent: IrDeclarationParent?) { - if (irParent != null) { - parent = irParent - if (irParent is IrExternalPackageFragment) { - irParent.declarations += this - } - } - } - - private fun T.declareDefaultSetterParameter(type: IrType, firValueParameter: FirValueParameter?): T { - valueParameters = listOf( - createDefaultSetterParameter(startOffset, endOffset, type, parent = this, firValueParameter) - ) - return this - } - - internal fun createDefaultSetterParameter( - startOffset: Int, - endOffset: Int, - type: IrType, - parent: IrFunction, - firValueParameter: FirValueParameter?, - name: Name? = null, - isCrossinline: Boolean = false, - isNoinline: Boolean = false, - ): IrValueParameter { - return irFactory.createValueParameter( - startOffset = startOffset, - endOffset = endOffset, - origin = IrDeclarationOrigin.DEFINED, - name = name ?: SpecialNames.IMPLICIT_SET_PARAMETER, - type = type, - isAssignable = false, - symbol = IrValueParameterSymbolImpl(), - index = parent.contextReceiverParametersCount, - varargElementType = null, - isCrossinline = isCrossinline, - isNoinline = isNoinline, - isHidden = false, - ).apply { - this.parent = parent - if (firValueParameter != null) { - annotationGenerator.generate(this, firValueParameter) - } - } - } - - fun addContextReceiverParametersTo( - contextReceivers: List, - parent: IrFunction, - result: MutableList, - ) { - contextReceivers.mapIndexedTo(result) { index, contextReceiver -> - createIrParameterFromContextReceiver(contextReceiver, index).apply { - this.parent = parent - } - } - } - - /* - * In perfect world dispatchReceiverType should always be the default type of containing class - * But fake-overrides for members from Any have special rules for type of dispatch receiver - */ - private fun IrFunction.declareParameters( - function: FirFunction?, - irParent: IrDeclarationParent?, - dispatchReceiverType: IrType?, // has no sense for constructors - isStatic: Boolean, - forSetter: Boolean, - // Can be not-null only for property accessors - parentPropertyReceiver: FirReceiverParameter? = null - ) { - val containingClass = computeContainingClass(irParent) - val parent = this - if (function is FirSimpleFunction || function is FirConstructor) { - with(classifierStorage) { - setTypeParameters(function) - } - } - val typeOrigin = if (forSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT - if (function is FirDefaultPropertySetter) { - val valueParameter = function.valueParameters.first() - val type = valueParameter.returnTypeRef.toIrType(ConversionTypeOrigin.SETTER) - declareDefaultSetterParameter(type, valueParameter) - } else if (function != null) { - val contextReceivers = function.contextReceiversForFunctionOrContainingProperty() - - contextReceiverParametersCount = contextReceivers.size - valueParameters = buildList { - addContextReceiverParametersTo(contextReceivers, parent, this) - - function.valueParameters.mapIndexedTo(this) { index, valueParameter -> - createIrParameter( - valueParameter, index + contextReceiverParametersCount, - useStubForDefaultValueStub = function !is FirConstructor || containingClass?.name != Name.identifier("Enum"), - typeOrigin, - skipDefaultParameter = isFakeOverride || origin == IrDeclarationOrigin.DELEGATED_MEMBER - ).apply { - this.parent = parent - } - } - } - } - - val thisOrigin = IrDeclarationOrigin.DEFINED - if (function !is FirConstructor) { - val receiver: FirReceiverParameter? = - if (function !is FirPropertyAccessor && function != null) function.receiverParameter - else parentPropertyReceiver - if (receiver != null) { - extensionReceiverParameter = receiver.convertWithOffsets { startOffset, endOffset -> - val name = (function as? FirAnonymousFunction)?.label?.name?.let { - val suffix = it.takeIf(Name::isValidIdentifier) ?: "\$receiver" - Name.identifier("\$this\$$suffix") - } ?: SpecialNames.THIS - declareThisReceiverParameter( - thisType = receiver.typeRef.toIrType(typeOrigin), - thisOrigin = thisOrigin, - startOffset = startOffset, - endOffset = endOffset, - name = name, - explicitReceiver = receiver, - ) - } - } - // See [LocalDeclarationsLowering]: "local function must not have dispatch receiver." - val isLocal = function is FirSimpleFunction && function.isLocal - if (function !is FirAnonymousFunction && dispatchReceiverType != null && !isStatic && !isLocal) { - dispatchReceiverParameter = declareThisReceiverParameter( - thisType = dispatchReceiverType, - thisOrigin = thisOrigin - ) - } - } else { - // Set dispatch receiver parameter for inner class's constructor. - val outerClass = containingClass?.parentClassOrNull - if (containingClass?.isInner == true && outerClass != null) { - dispatchReceiverParameter = declareThisReceiverParameter( - thisType = outerClass.thisReceiver!!.type, - thisOrigin = thisOrigin - ) - } - } - } - fun T.putParametersInScope(function: FirFunction): T { val contextReceivers = function.contextReceiversForFunctionOrContainingProperty() @@ -645,23 +424,13 @@ class Fir2IrDeclarationStorage( fun originalDeclarationForDelegated(irDeclaration: IrDeclaration): FirDeclaration? = delegatedReverseCache[irDeclaration] - internal fun declareIrSimpleFunction( - signature: IdSignature?, - factory: (IrSimpleFunctionSymbol) -> IrSimpleFunction - ): IrSimpleFunction = - if (signature == null) { - factory(IrSimpleFunctionSymbolImpl()) - } else { - symbolTable.declareSimpleFunction(signature, { Fir2IrSimpleFunctionSymbol(signature) }, factory) - } - fun getOrCreateIrFunction( function: FirSimpleFunction, irParent: IrDeclarationParent?, isLocal: Boolean = false, ): IrSimpleFunction { getCachedIrFunction(function)?.let { return it } - return createIrFunction( + return callablesGenerator.createIrFunction( function, irParent, isLocal = isLocal, @@ -669,132 +438,9 @@ class Fir2IrDeclarationStorage( ) } - fun createIrFunction( - function: FirFunction, - irParent: IrDeclarationParent?, - predefinedOrigin: IrDeclarationOrigin? = null, - isLocal: Boolean = false, - fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null, - ): IrSimpleFunction = convertCatching(function) { - val simpleFunction = function as? FirSimpleFunction - val isLambda = function is FirAnonymousFunction && function.isLambda - val updatedOrigin = when { - isLambda -> IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA - function.symbol.callableId.isKFunctionInvoke() -> IrDeclarationOrigin.FAKE_OVERRIDE - simpleFunction?.isStatic == true && simpleFunction.name in ENUM_SYNTHETIC_NAMES -> IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER - - // Kotlin built-in class and Java originated method (Collection.forEach, etc.) - // It's necessary to understand that such methods do not belong to DefaultImpls but actually generated as default - // See org.jetbrains.kotlin.backend.jvm.lower.InheritedDefaultMethodsOnClassesLoweringKt.isDefinitelyNotDefaultImplsMethod - (irParent as? IrClass)?.origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB && - function.isJavaOrEnhancement -> IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB - else -> function.computeIrOrigin(predefinedOrigin) - } - // 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 && irParent !is Fir2IrLazyClass && - function.dispatchReceiverType?.isPrimitive != true && function.containerSource == null && - updatedOrigin != IrDeclarationOrigin.FAKE_OVERRIDE && !function.isOverride - ) { - signatureComposer.composeSignature(function, fakeOverrideOwnerLookupTag) - } - 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) - } - val name = simpleFunction?.name - ?: if (isLambda) SpecialNames.ANONYMOUS else SpecialNames.NO_NAME_PROVIDED - val visibility = simpleFunction?.visibility ?: Visibilities.Local - val isSuspend = - if (isLambda) ((function as FirAnonymousFunction).typeRef as? FirResolvedTypeRef)?.type?.isSuspendOrKSuspendFunctionType(session) == true - else function.isSuspend - val created = function.convertWithOffsets { startOffset, endOffset -> - val result = 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) - enterScope(this.symbol) - setAndModifyParent(irParent) - declareParameters( - function, irParent, - dispatchReceiverType = computeDispatchReceiverType(this, simpleFunction, irParent), - isStatic = simpleFunction?.isStatic == true, - forSetter = false, - ) - convertAnnotationsForNonDeclaredMembers(function, origin) - leaveScope(this.symbol) - } - } - result - } - - if (visibility == Visibilities.Local) { - localStorage.putLocalFunction(function, created) - return created - } - if (function.symbol.callableId.isKFunctionInvoke()) { - (function.symbol.originalForSubstitutionOverride as? FirNamedFunctionSymbol)?.let { - created.overriddenSymbols += getIrFunctionSymbol(it) as IrSimpleFunctionSymbol - } - } - if (function.isFakeOverride(fakeOverrideOwnerLookupTag)) { - val originalFunction = function.unwrapFakeOverrides() - val key = FakeOverrideIdentifier( - originalFunction.symbol, - fakeOverrideOwnerLookupTag ?: function.containingClassLookupTag()!! - ) - irFakeOverridesForFirFakeOverrideMap[key] = created - } else { - functionCache[function] = created - } - return created - } - fun getCachedIrAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer): IrAnonymousInitializer? = initializerCache[anonymousInitializer] - fun createIrAnonymousInitializer( - anonymousInitializer: FirAnonymousInitializer, - irParent: IrClass - ): IrAnonymousInitializer = convertCatching(anonymousInitializer) { - return anonymousInitializer.convertWithOffsets { startOffset, endOffset -> - symbolTable.descriptorExtension.declareAnonymousInitializer( - startOffset, - endOffset, - IrDeclarationOrigin.DEFINED, - irParent.descriptor - ).apply { - this.parent = irParent - initializerCache[anonymousInitializer] = this - } - } - } - @OptIn(IrSymbolInternals::class) fun getCachedIrConstructor( constructor: FirConstructor, @@ -809,55 +455,6 @@ class Fir2IrDeclarationStorage( } } - private fun declareIrConstructor(signature: IdSignature?, factory: (IrConstructorSymbol) -> IrConstructor): IrConstructor = - if (signature == null) - factory(IrConstructorSymbolImpl()) - else - symbolTable.declareConstructor(signature, { Fir2IrConstructorSymbol(signature) }, factory) - - - fun createIrConstructor( - constructor: FirConstructor, - irParent: IrClass, - predefinedOrigin: IrDeclarationOrigin? = null, - isLocal: Boolean = false, - ): IrConstructor = convertCatching(constructor) { - val origin = constructor.computeIrOrigin(predefinedOrigin) - val isPrimary = constructor.isPrimary - val signature = - runUnless(isLocal || !configuration.linkViaSignatures) { - signatureComposer.composeSignature(constructor) - } - val visibility = if (irParent.isAnonymousObject) Visibilities.Public else constructor.visibility - return constructor.convertWithOffsets { startOffset, endOffset -> - declareIrConstructor(signature) { symbol -> - classifierStorage.preCacheTypeParameters(constructor, symbol) - irFactory.createConstructor( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - name = SpecialNames.INIT, - visibility = components.visibilityConverter.convertToDescriptorVisibility(visibility), - isInline = false, - isExpect = constructor.isExpect, - returnType = constructor.returnTypeRef.toIrType(), - symbol = symbol, - isPrimary = isPrimary, - isExternal = false, - ).apply { - metadata = FirMetadataSource.Function(constructor) - // Add to cache before generating parameters to prevent an infinite loop when an annotation value parameter is annotated - // with the annotation itself. - constructorCache[constructor] = this - enterScope(this.symbol) - setAndModifyParent(irParent) - declareParameters(constructor, irParent, dispatchReceiverType = null, isStatic = false, forSetter = false) - leaveScope(this.symbol) - } - } - } - } - fun getOrCreateIrConstructor( constructor: FirConstructor, irParent: IrClass, @@ -865,164 +462,16 @@ class Fir2IrDeclarationStorage( isLocal: Boolean = false, ): IrConstructor { getCachedIrConstructor(constructor)?.let { return it } - return createIrConstructor(constructor, irParent, predefinedOrigin, isLocal) + return callablesGenerator.createIrConstructor(constructor, irParent, predefinedOrigin, isLocal) } - private fun declareIrAccessor( - signature: IdSignature?, - factory: (IrSimpleFunctionSymbol) -> IrSimpleFunction - ): IrSimpleFunction = - if (signature == null) - factory(IrSimpleFunctionSymbolImpl()) - else - symbolTable.declareSimpleFunction(signature, { Fir2IrSimpleFunctionSymbol(signature) }, factory) - - private fun createIrPropertyAccessor( - propertyAccessor: FirPropertyAccessor?, - property: FirProperty, - correspondingProperty: IrDeclarationWithName, - propertyType: IrType, - irParent: IrDeclarationParent?, - isSetter: Boolean, - origin: IrDeclarationOrigin, - startOffset: Int, - endOffset: Int, - dontUseSignature: Boolean = false, - fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null, - propertyAccessorForAnnotations: FirPropertyAccessor? = propertyAccessor, - ): IrSimpleFunction = convertCatching(propertyAccessor ?: property) { - val prefix = if (isSetter) "set" else "get" - val signature = - runUnless(dontUseSignature) { - signatureComposer.composeAccessorSignature(property, isSetter, fakeOverrideOwnerLookupTag) - } - val containerSource = (correspondingProperty as? IrProperty)?.containerSource - return declareIrAccessor( - signature - ) { symbol -> - val accessorReturnType = if (isSetter) irBuiltIns.unitType else propertyType - val visibility = propertyAccessor?.visibility?.let { - components.visibilityConverter.convertToDescriptorVisibility(it) - } - irFactory.createSimpleFunction( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - name = Name.special("<$prefix-${correspondingProperty.name}>"), - visibility = visibility ?: (correspondingProperty as IrDeclarationWithVisibility).visibility, - isInline = propertyAccessor?.isInline == true, - isExpect = false, - returnType = accessorReturnType, - modality = (correspondingProperty as? IrOverridableMember)?.modality ?: Modality.FINAL, - symbol = symbol, - isTailrec = false, - isSuspend = false, - isOperator = false, - isInfix = false, - isExternal = propertyAccessor?.isExternal == true, - containerSource = containerSource, - ).apply { - correspondingPropertySymbol = (correspondingProperty as? IrProperty)?.symbol - if (propertyAccessor != null) { - metadata = FirMetadataSource.Function(propertyAccessor) - // Note that deserialized annotations are stored in the accessor, not the property. - convertAnnotationsForNonDeclaredMembers(propertyAccessor, origin) - } - - if (propertyAccessorForAnnotations != null) { - convertAnnotationsForNonDeclaredMembers(propertyAccessorForAnnotations, origin) - } - with(classifierStorage) { - setTypeParameters( - property, if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT - ) - } - // NB: we should enter accessor' scope before declaring its parameters - // (both setter default and receiver ones, if any) - enterScope(this.symbol) - if (propertyAccessor == null && isSetter) { - declareDefaultSetterParameter( - property.returnTypeRef.toIrType(ConversionTypeOrigin.SETTER), - firValueParameter = null - ) - } - setAndModifyParent(irParent) - val dispatchReceiverType = computeDispatchReceiverType(this, property, irParent) - declareParameters( - propertyAccessor, irParent, dispatchReceiverType, - isStatic = irParent !is IrClass || propertyAccessor?.isStatic == true, forSetter = isSetter, - parentPropertyReceiver = property.receiverParameter, - ) - leaveScope(this.symbol) - if (correspondingProperty is Fir2IrLazyProperty && correspondingProperty.containingClass != null && !isFakeOverride && dispatchReceiverType != null) { - this.overriddenSymbols = correspondingProperty.fir.generateOverriddenAccessorSymbols( - correspondingProperty.containingClass, !isSetter - ) - } - } - } - } - - internal fun IrProperty.createBackingField( - property: FirProperty, - origin: IrDeclarationOrigin, - visibility: DescriptorVisibility, - name: Name, - isFinal: Boolean, - firInitializerExpression: FirExpression?, - type: IrType? = null - ): IrField = convertCatching(property) { - val inferredType = type ?: firInitializerExpression!!.resolvedType.toIrType() - return declareIrField { symbol -> - irFactory.createField( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - name = name, - visibility = visibility, - symbol = symbol, - type = inferredType, - isFinal = isFinal, - isStatic = property.isStatic || !(parent is IrClass || parent is IrScript), - isExternal = property.isExternal, - ).also { - it.correspondingPropertySymbol = this@createBackingField.symbol - }.apply { - metadata = FirMetadataSource.Property(property) - convertAnnotationsForNonDeclaredMembers(property, origin) - } - } - } - - private val FirProperty.fieldVisibility: Visibility - get() = when { - hasExplicitBackingField -> backingField?.visibility ?: status.visibility - isLateInit -> setter?.visibility ?: status.visibility - isConst -> status.visibility - hasJvmFieldAnnotation(session) -> status.visibility - origin == FirDeclarationOrigin.ScriptCustomization.ResultProperty -> status.visibility - else -> Visibilities.Private - } - - private fun declareIrProperty( - signature: IdSignature?, - factory: (IrPropertySymbol) -> IrProperty - ): IrProperty = - if (signature == null) - factory(IrPropertySymbolImpl()) - else - symbolTable.declareProperty(signature, { Fir2IrPropertySymbol(signature) }, factory) - - private fun declareIrField(factory: (IrFieldSymbol) -> IrField): IrField = - factory(IrFieldSymbolImpl()) - fun getOrCreateIrProperty( property: FirProperty, irParent: IrDeclarationParent?, isLocal: Boolean = false, ): IrProperty { getCachedIrProperty(property)?.let { return it } - return createIrProperty(property, irParent, isLocal = isLocal) + return callablesGenerator.createIrProperty(property, irParent, isLocal = isLocal) } fun getOrCreateIrPropertyByPureField( @@ -1031,7 +480,7 @@ class Fir2IrDeclarationStorage( ): IrProperty { return fieldToPropertyCache.getOrPut(field to irParent) { val containingClassId = (irParent as? IrClass)?.classId - createIrProperty( + callablesGenerator.createIrProperty( field.toStubProperty(), irParent, fakeOverrideOwnerLookupTag = containingClassId?.toLookupTag() @@ -1058,10 +507,6 @@ class Fir2IrDeclarationStorage( } } - private object IsStubPropertyForPureFieldKey : FirDeclarationDataKey() - - private var FirProperty.isStubPropertyForPureField: Boolean? by FirDeclarationDataRegistry.data(IsStubPropertyForPureFieldKey) - fun findGetterOfProperty(propertySymbol: IrPropertySymbol): IrSimpleFunctionSymbol? { return getterForPropertyCache[propertySymbol] } @@ -1090,164 +535,6 @@ class Fir2IrDeclarationStorage( return delegateVariableForPropertyCache.getValue(propertySymbol) } - fun createIrProperty( - property: FirProperty, - irParent: IrDeclarationParent?, - predefinedOrigin: IrDeclarationOrigin? = null, - isLocal: Boolean = false, - fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null, - ): IrProperty = convertCatching(property) { - val origin = - if (property.isStatic && property.name in ENUM_SYNTHETIC_NAMES) IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER - else property.computeIrOrigin(predefinedOrigin) - // See similar comments in createIrFunction above - val signature = - runUnless( - isLocal || - !configuration.linkViaSignatures && irParent !is Fir2IrLazyClass && - property.dispatchReceiverType?.isPrimitive != true && property.containerSource == null && - origin != IrDeclarationOrigin.FAKE_OVERRIDE && !property.isOverride - ) { - signatureComposer.composeSignature(property, fakeOverrideOwnerLookupTag) - } - if (irParent is Fir2IrLazyClass && signature != null) { - // For private functions signature is null, fallback to non-lazy property - return createIrLazyProperty(property, signature, irParent, origin) - } - return property.convertWithOffsets { startOffset, endOffset -> - val result = declareIrProperty(signature) { symbol -> - classifierStorage.preCacheTypeParameters(property, symbol) - irFactory.createProperty( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - name = property.name, - visibility = components.visibilityConverter.convertToDescriptorVisibility(property.visibility), - modality = property.modality!!, - symbol = symbol, - isVar = property.isVar, - isConst = property.isConst, - isLateinit = property.isLateInit, - isDelegated = property.delegate != null, - isExternal = property.isExternal, - containerSource = property.containerSource, - isExpect = property.isExpect, - ).apply { - metadata = FirMetadataSource.Property(property) - convertAnnotationsForNonDeclaredMembers(property, origin) - enterScope(this.symbol) - if (irParent != null) { - parent = irParent - } - val type = property.returnTypeRef.toIrType() - val delegate = property.delegate - val getter = property.getter - val setter = property.setter - if (delegate != null || property.hasBackingField) { - val backingField = if (delegate != null) { - ((delegate as? FirQualifiedAccessExpression)?.calleeReference?.toResolvedBaseSymbol()?.fir as? FirTypeParameterRefsOwner)?.let { - classifierStorage.preCacheTypeParameters(it, symbol) - } - createBackingField( - property, IrDeclarationOrigin.PROPERTY_DELEGATE, - components.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility), - NameUtils.propertyDelegateName(property.name), true, delegate - ) - } else { - val initializer = getEffectivePropertyInitializer(property, resolveIfNeeded = true) - // There are cases when we get here for properties - // that have no backing field. For example, in the - // funExpression.kt test there's an attempt - // to access the `javaClass` property of the `foo0`'s - // `block` argument - val typeToUse = property.backingField?.returnTypeRef?.toIrType() ?: type - createBackingField( - property, IrDeclarationOrigin.PROPERTY_BACKING_FIELD, - components.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility), - property.name, property.isVal, initializer, typeToUse - ).also { field -> - if (initializer is FirConstExpression<*>) { - val constType = initializer.resolvedType.toIrType() - field.initializer = factory.createExpressionBody(initializer.toIrConst(constType)) - } - } - } - backingField.symbol.let { - backingFieldForPropertyCache[symbol] = it - propertyForBackingFieldCache[it] = symbol - } - this.backingField = backingField - } - if (irParent != null) { - backingField?.parent = irParent - } - this.getter = createIrPropertyAccessor( - getter, property, this, type, irParent, false, - when { - origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin - origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER -> origin - delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR - origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin - origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin - getter == null || getter is FirDefaultPropertyGetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR - else -> origin - }, - startOffset, endOffset, - dontUseSignature = signature == null, fakeOverrideOwnerLookupTag, - property.unwrapFakeOverrides().getter, - ).also { - getterForPropertyCache[symbol] = it.symbol - } - if (property.isVar) { - this.setter = createIrPropertyAccessor( - setter, property, this, type, irParent, true, - when { - delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR - origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin - origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin - setter is FirDefaultPropertySetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR - else -> origin - }, - startOffset, endOffset, - dontUseSignature = signature == null, fakeOverrideOwnerLookupTag, - property.unwrapFakeOverrides().setter, - ).also { - setterForPropertyCache[symbol] = it.symbol - } - } - leaveScope(this.symbol) - } - } - if (property.isFakeOverride(fakeOverrideOwnerLookupTag)) { - val originalProperty = property.unwrapFakeOverrides() - val key = FakeOverrideIdentifier( - originalProperty.symbol, - fakeOverrideOwnerLookupTag ?: property.containingClassLookupTag()!! - ) - irFakeOverridesForFirFakeOverrideMap[key] = result - } else { - propertyCache[property] = result - } - result - } - } - - /** - * In partial module compilation (see [org.jetbrains.kotlin.analysis.api.fir.components.KtFirCompilerFacility]), - * referenced properties might be resolved only up to [FirResolvePhase.CONTRACTS], - * however the backend requires the exact initializer type. - */ - private fun getEffectivePropertyInitializer(property: FirProperty, resolveIfNeeded: Boolean): FirExpression? { - val initializer = property.backingField?.initializer ?: property.initializer - - if (resolveIfNeeded && initializer is FirConstExpression<*>) { - property.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE) - return getEffectivePropertyInitializer(property, resolveIfNeeded = false) - } - - return initializer - } - fun getCachedIrProperty(property: FirProperty): IrProperty? { return getCachedIrProperty(property, fakeOverrideOwnerLookupTag = null) { signatureComposer.composeSignature(property) @@ -1350,19 +637,7 @@ class Fir2IrDeclarationStorage( return fieldStaticOverrideCache[FieldStaticOverrideKey(ownerLookupTag, field.name)] } - fun createIrFieldAndDelegatedMembers(field: FirField, owner: FirClass, irClass: IrClass): IrField? { - // Either take a corresponding constructor property backing field, - // or create a separate delegate field - val irField = getOrCreateDelegateIrField(field, owner, irClass) - delegatedMemberGenerator.generate(irField, field, owner, irClass) - if (owner.isLocalClassOrAnonymousObject()) { - delegatedMemberGenerator.generateBodies() - } - // If it's a property backing field, it should not be added to the class in Fir2IrConverter, so it's not returned - return irField.takeIf { it.correspondingPropertySymbol == null } - } - - private fun getOrCreateDelegateIrField(field: FirField, owner: FirClass, irClass: IrClass): IrField { + internal fun getOrCreateDelegateIrField(field: FirField, owner: FirClass, irClass: IrClass): IrField { val initializer = field.initializer if (initializer is FirQualifiedAccessExpression && initializer.explicitReceiver == null) { val resolvedSymbol = initializer.calleeReference.toResolvedValueParameterSymbol() @@ -1379,7 +654,7 @@ class Fir2IrDeclarationStorage( } } } - return createIrField( + return callablesGenerator.createIrField( field, irParent = irClass, type = initializer?.resolvedType ?: field.returnTypeRef.coneType, @@ -1389,64 +664,6 @@ class Fir2IrDeclarationStorage( } } - internal fun createIrField( - field: FirField, - irParent: IrDeclarationParent?, - type: ConeKotlinType = field.returnTypeRef.coneType, - origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB - ): IrField = convertCatching(field) { - val irType = type.toIrType() - val classId = (irParent as? IrClass)?.classId - val containingClassLookupTag = classId?.toLookupTag() - val signature = signatureComposer.composeSignature(field, containingClassLookupTag) - return field.convertWithOffsets { startOffset, endOffset -> - if (signature != null) { - symbolTable.declareField( - signature, symbolFactory = { IrFieldPublicSymbolImpl(signature) } - ) { symbol -> - irFactory.createField( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - name = field.name, - visibility = components.visibilityConverter.convertToDescriptorVisibility(field.visibility), - symbol = symbol, - type = irType, - isFinal = field.modality == Modality.FINAL, - isStatic = field.isStatic, - isExternal = false - ) - } - } else { - irFactory.createField( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - name = field.name, - visibility = components.visibilityConverter.convertToDescriptorVisibility(field.visibility), - symbol = IrFieldSymbolImpl(), - type = irType, - isFinal = field.modality == Modality.FINAL, - isStatic = field.isStatic, - isExternal = false - ) - }.apply { - metadata = FirMetadataSource.Field(field) - val staticFakeOverrideKey = getFieldStaticFakeOverrideKey(field, containingClassLookupTag) - if (staticFakeOverrideKey == null) { - fieldCache[field] = this - } else { - fieldStaticOverrideCache[staticFakeOverrideKey] = this - } - val initializer = field.unwrapFakeOverrides().initializer - if (initializer is FirConstExpression<*>) { - this.initializer = factory.createExpressionBody(initializer.toIrConst(irType)) - } - setAndModifyParent(irParent) - } - } - } - // This function returns null if this field/ownerClassId combination does not describe static fake override private fun getFieldStaticFakeOverrideKey(field: FirField, ownerLookupTag: ConeClassLikeLookupTag?): FieldStaticOverrideKey? { if (ownerLookupTag == null || !field.isStatic || @@ -1455,184 +672,6 @@ class Fir2IrDeclarationStorage( return FieldStaticOverrideKey(ownerLookupTag, field.name) } - internal fun createIrParameter( - valueParameter: FirValueParameter, - index: Int = UNDEFINED_PARAMETER_INDEX, - useStubForDefaultValueStub: Boolean = true, - typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT, - skipDefaultParameter: Boolean = false, - // Use this parameter if you want to insert the actual default value instead of the stub (overrides useStubForDefaultValueStub parameter). - // This parameter is intended to be used for default values of annotation parameters where they are needed and - // may produce incorrect results for values that may be encountered outside annotations. - // Does not do anything if valueParameter.defaultValue is already FirExpressionStub. - forcedDefaultValueConversion: Boolean = false, - ): IrValueParameter = convertCatching(valueParameter) { - val origin = valueParameter.computeIrOrigin() - val type = valueParameter.returnTypeRef.toIrType(typeOrigin) - val irParameter = valueParameter.convertWithOffsets { startOffset, endOffset -> - irFactory.createValueParameter( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - name = valueParameter.name, - type = type, - isAssignable = false, - symbol = IrValueParameterSymbolImpl(), - index = index, - varargElementType = valueParameter.varargElementType?.toIrType(typeOrigin), - isCrossinline = valueParameter.isCrossinline, - isNoinline = valueParameter.isNoinline, - isHidden = false, - ).apply { - val defaultValue = valueParameter.defaultValue - if (!skipDefaultParameter && defaultValue != null) { - this.defaultValue = when { - forcedDefaultValueConversion && defaultValue !is FirExpressionStub -> - defaultValue.asCompileTimeIrInitializer(components) - useStubForDefaultValueStub || defaultValue !is FirExpressionStub -> - factory.createExpressionBody( - IrErrorExpressionImpl( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, - "Stub expression for default value of ${valueParameter.name}" - ) - ) - else -> null - } - } - annotationGenerator.generate(this, valueParameter) - } - } - localStorage.putParameter(valueParameter, irParameter) - return irParameter - } - - private fun createIrParameterFromContextReceiver( - contextReceiver: FirContextReceiver, - index: Int, - ): IrValueParameter = convertCatching(contextReceiver) { - val type = contextReceiver.typeRef.toIrType() - return contextReceiver.convertWithOffsets { startOffset, endOffset -> - irFactory.createValueParameter( - startOffset = startOffset, - endOffset = endOffset, - origin = IrDeclarationOrigin.DEFINED, - name = NameUtils.contextReceiverName(index), - type = type, - isAssignable = false, - symbol = IrValueParameterSymbolImpl(), - index = index, - varargElementType = null, - isCrossinline = false, - isNoinline = false, - isHidden = false, - ) - } - } - - // TODO: KT-58686 - private var lastTemporaryIndex: Int = 0 - private fun nextTemporaryIndex(): Int = lastTemporaryIndex++ - - private fun getNameForTemporary(nameHint: String?): String { - val index = nextTemporaryIndex() - return if (nameHint != null) "tmp${index}_$nameHint" else "tmp$index" - } - - private fun declareIrVariable( - startOffset: Int, endOffset: Int, - origin: IrDeclarationOrigin, name: Name, type: IrType, - isVar: Boolean, isConst: Boolean, isLateinit: Boolean - ): IrVariable = - IrVariableImpl( - startOffset, endOffset, origin, IrVariableSymbolImpl(), name, type, - isVar, isConst, isLateinit - ) - - fun createIrVariable( - variable: FirVariable, - irParent: IrDeclarationParent, - givenOrigin: IrDeclarationOrigin? = null - ): IrVariable = convertCatching(variable) { - val type = variable.irTypeForPotentiallyComponentCall() - // Some temporary variables are produced in RawFirBuilder, but we consistently use special names for them. - val origin = when { - givenOrigin != null -> givenOrigin - variable.name == SpecialNames.ITERATOR -> IrDeclarationOrigin.FOR_LOOP_ITERATOR - variable.name.isSpecial -> IrDeclarationOrigin.IR_TEMPORARY_VARIABLE - else -> IrDeclarationOrigin.DEFINED - } - val isLateInit = if (variable is FirProperty) variable.isLateInit else false - val irVariable = variable.convertWithOffsets { startOffset, endOffset -> - declareIrVariable( - startOffset, endOffset, origin, - variable.name, type, variable.isVar, isConst = false, isLateinit = isLateInit - ) - } - irVariable.parent = irParent - localStorage.putVariable(variable, irVariable) - return irVariable - } - - fun createIrLocalDelegatedProperty( - property: FirProperty, - irParent: IrDeclarationParent - ): IrLocalDelegatedProperty = convertCatching(property) { - val type = property.returnTypeRef.toIrType() - val origin = IrDeclarationOrigin.DEFINED - val symbol = IrLocalDelegatedPropertySymbolImpl() - val irProperty = property.convertWithOffsets { startOffset, endOffset -> - irFactory.createLocalDelegatedProperty( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - name = property.name, - symbol = symbol, - type = type, - isVar = property.isVar - ) - }.apply { - parent = irParent - metadata = FirMetadataSource.Property(property) - enterScope(this.symbol) - delegate = declareIrVariable( - startOffset, endOffset, IrDeclarationOrigin.PROPERTY_DELEGATE, - NameUtils.propertyDelegateName(property.name), property.delegate!!.resolvedType.toIrType(), - isVar = false, isConst = false, isLateinit = false - ).also { - delegateVariableForPropertyCache[symbol] = it.symbol - } - delegate.parent = irParent - getter = createIrPropertyAccessor( - property.getter, property, this, type, irParent, false, - IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, startOffset, endOffset, dontUseSignature = true - ).also { - getterForPropertyCache[symbol] = it.symbol - } - if (property.isVar) { - setter = createIrPropertyAccessor( - property.setter, property, this, type, irParent, true, - IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, startOffset, endOffset, dontUseSignature = true - ).also { - setterForPropertyCache[symbol] = it.symbol - } - } - annotationGenerator.generate(this, property) - leaveScope(this.symbol) - } - localStorage.putDelegatedProperty(property, irProperty) - return irProperty - } - - fun declareTemporaryVariable(base: IrExpression, nameHint: String? = null): IrVariable { - return declareIrVariable( - base.startOffset, base.endOffset, IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, - Name.identifier(getNameForTemporary(nameHint)), base.type, - isVar = false, isConst = false, isLateinit = false - ).apply { - initializer = base - } - } - fun getIrConstructorSymbol(firConstructorSymbol: FirConstructorSymbol): IrConstructorSymbol { val fir = firConstructorSymbol.fir return getIrCallableSymbol( @@ -1640,7 +679,7 @@ class Fir2IrDeclarationStorage( fakeOverrideOwnerLookupTag = null, getCachedIrDeclaration = { constructor: FirConstructor, _, calculator -> getCachedIrConstructor(constructor, calculator) }, createIrDeclaration = { parent, origin -> - createIrConstructor(fir, parent as IrClass, predefinedOrigin = origin) + callablesGenerator.createIrConstructor(fir, parent as IrClass, predefinedOrigin = origin) }, createIrLazyDeclaration = { signature, lazyParent, declarationOrigin -> val symbol = Fir2IrConstructorSymbol(signature) @@ -1672,7 +711,7 @@ class Fir2IrDeclarationStorage( val irParent = findIrParent(fir) val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED val declarationOrigin = computeDeclarationOrigin(firFunctionSymbol, parentOrigin) - createIrFunction(fir, irParent, predefinedOrigin = declarationOrigin).symbol + callablesGenerator.createIrFunction(fir, irParent, predefinedOrigin = declarationOrigin).symbol } is FirSimpleFunction -> { val unmatchedOwner = fakeOverrideOwnerLookupTag != firFunctionSymbol.containingClassLookupTag() @@ -1684,14 +723,14 @@ class Fir2IrDeclarationStorage( fakeOverrideOwnerLookupTag, getCachedIrDeclaration = ::getCachedIrFunction, createIrDeclaration = { parent, origin -> - createIrFunction( + callablesGenerator.createIrFunction( fir, parent, predefinedOrigin = origin, fakeOverrideOwnerLookupTag = fakeOverrideOwnerLookupTag, ) }, createIrLazyDeclaration = { signature, lazyParent, declarationOrigin -> - createIrLazyFunction(fir, signature, lazyParent, declarationOrigin) + lazyDeclarationsGenerator.createIrLazyFunction(fir, signature, lazyParent, declarationOrigin) }, ) as IrFunctionSymbol if (unmatchedOwner && fakeOverrideOwnerLookupTag is ConeClassLookupTagWithFixedSymbol) { @@ -1708,29 +747,6 @@ class Fir2IrDeclarationStorage( } } - private fun createIrLazyFunction( - fir: FirSimpleFunction, - signature: IdSignature, - lazyParent: IrDeclarationParent, - declarationOrigin: IrDeclarationOrigin - ): IrSimpleFunction { - val symbol = symbolTable.referenceSimpleFunction(signature) - val irFunction = fir.convertWithOffsets { startOffset, endOffset -> - symbolTable.declareSimpleFunction(signature, { symbol }) { - val isFakeOverride = fir.isSubstitutionOrIntersectionOverride - Fir2IrLazySimpleFunction( - components, startOffset, endOffset, declarationOrigin, - fir, (lazyParent as? Fir2IrLazyClass)?.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 - } @OptIn(IrSymbolInternals::class) fun getIrPropertySymbol( @@ -1752,12 +768,12 @@ class Fir2IrDeclarationStorage( fakeOverrideOwnerLookupTag = this, getCachedIrDeclaration = ::getCachedIrProperty, createIrDeclaration = { parent, origin -> - createIrProperty( + callablesGenerator.createIrProperty( fir, parent, predefinedOrigin = origin, fakeOverrideOwnerLookupTag = fakeOverrideOwnerLookupTag, ) }, createIrLazyDeclaration = { signature, lazyParent, declarationOrigin -> - createIrLazyProperty(fir, signature, lazyParent, declarationOrigin) + lazyDeclarationsGenerator.createIrLazyProperty(fir, signature, lazyParent, declarationOrigin) }, ) @@ -1785,51 +801,6 @@ class Fir2IrDeclarationStorage( } } - @OptIn(IrSymbolInternals::class) - private fun createIrLazyProperty( - fir: FirProperty, - signature: IdSignature, - lazyParent: IrDeclarationParent, - declarationOrigin: IrDeclarationOrigin - ): IrProperty { - val symbol = Fir2IrPropertySymbol(signature) - val firPropertySymbol = fir.symbol - - fun create(startOffset: Int, endOffset: Int): Fir2IrLazyProperty { - val isFakeOverride = - fir.isSubstitutionOrIntersectionOverride && - firPropertySymbol.dispatchReceiverClassLookupTagOrNull() != - firPropertySymbol.originalForSubstitutionOverride?.dispatchReceiverClassLookupTagOrNull() - return Fir2IrLazyProperty( - components, startOffset, endOffset, declarationOrigin, - fir, (lazyParent as? Fir2IrLazyClass)?.fir, symbol, isFakeOverride - ).apply { - this.parent = lazyParent - } - } - - val irProperty = fir.convertWithOffsets { startOffset, endOffset -> - if (fir.isStubPropertyForPureField == true) { - // Very special case when two similar properties can exist so conflicts in SymbolTable are possible. - // See javaCloseFieldAndKotlinProperty.kt in BB tests - symbolTable.declarePropertyWithSignature(signature, symbol) - create(startOffset, endOffset) - symbol.owner - } else { - symbolTable.declareProperty(signature, { symbol }) { - create(startOffset, endOffset) - } - } - } - propertyCache[fir] = irProperty - irProperty.getter?.symbol?.let { getterForPropertyCache[symbol] = it } - irProperty.setter?.symbol?.let { setterForPropertyCache[symbol] = it } - irProperty.backingField?.symbol?.let { - backingFieldForPropertyCache[symbol] = it - propertyForBackingFieldCache[it] = symbol - } - return irProperty - } @OptIn(IrSymbolInternals::class) private inline fun > ConeClassLookupTagWithFixedSymbol.findIrFakeOverride( @@ -1911,7 +882,7 @@ class Fir2IrDeclarationStorage( } } return createIrDeclaration(irParent, declarationOrigin).apply { - (this as IrDeclaration).setAndModifyParent(irParent) + callablesGenerator.setAndModifyParent((this as IrDeclaration), irParent) }.symbol } } @@ -1948,7 +919,7 @@ class Fir2IrDeclarationStorage( if (unwrapped !== fir) { return getIrFieldSymbol(unwrapped.symbol) } - return createIrField(fir, irParent).symbol + return callablesGenerator.createIrField(fir, irParent).symbol } fun getIrBackingFieldSymbol(firBackingFieldSymbol: FirBackingFieldSymbol): IrSymbol { @@ -1986,8 +957,8 @@ class Fir2IrDeclarationStorage( propertyCache[fir]?.let { return it.backingField!!.symbol } val irParent = findIrParent(fir) val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED - createIrProperty(fir, irParent, predefinedOrigin = parentOrigin).apply { - setAndModifyParent(irParent) + callablesGenerator.createIrProperty(fir, irParent, predefinedOrigin = parentOrigin).also { + callablesGenerator.setAndModifyParent(it, irParent) }.backingField!!.symbol } else -> { @@ -2030,15 +1001,6 @@ class Fir2IrDeclarationStorage( } } - private fun IrMutableAnnotationContainer.convertAnnotationsForNonDeclaredMembers( - firAnnotationContainer: FirAnnotationContainer, origin: IrDeclarationOrigin, - ) { - if ((firAnnotationContainer as? FirDeclaration)?.let { it.isFromLibrary || it.isPrecompiled } == true - || origin == IrDeclarationOrigin.FAKE_OVERRIDE - ) { - annotationGenerator.generate(this, firAnnotationContainer) - } - } companion object { internal val ENUM_SYNTHETIC_NAMES = mapOf( @@ -2048,25 +1010,17 @@ class Fir2IrDeclarationStorage( Name.special("") to IrSyntheticBodyKind.ENUM_ENTRIES ) } - - private inline fun convertCatching(element: FirElement, block: () -> R): R { - try { - return block() - } catch (e: ProcessCanceledException) { - throw e - } catch (e: Exception) { - errorWithAttachment("Exception was thrown during transformation of ${element::class.java}", cause = e) { - withFirEntry("element", element) - } - } - } - - private fun FirCallableDeclaration.isFakeOverride(fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?): Boolean { - if (isSubstitutionOrIntersectionOverride) return true - if (fakeOverrideOwnerLookupTag == null) return false - // this condition is true for all places when we are trying to create "fake" fake overrides in IR - // "fake" fake overrides are f/o which are presented in IR but have no corresponding FIR f/o - return fakeOverrideOwnerLookupTag != containingClassLookupTag() - } - } + +internal fun FirCallableDeclaration.isFakeOverride(fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?): Boolean { + if (isSubstitutionOrIntersectionOverride) return true + if (fakeOverrideOwnerLookupTag == null) return false + // this condition is true for all places when we are trying to create "fake" fake overrides in IR + // "fake" fake overrides are f/o which are presented in IR but have no corresponding FIR f/o + return fakeOverrideOwnerLookupTag != containingClassLookupTag() +} + + +private object IsStubPropertyForPureFieldKey : FirDeclarationDataKey() + +internal var FirProperty.isStubPropertyForPureField: Boolean? by FirDeclarationDataRegistry.data(IsStubPropertyForPureFieldKey) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 287cffff51c..28ab41b5e64 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -220,7 +220,11 @@ class Fir2IrVisitor( declarationStorage.enterScope(irScript.symbol) irScript.explicitCallParameters = script.parameters.map { parameter -> - declarationStorage.createIrVariable(parameter, irScript, givenOrigin = IrDeclarationOrigin.SCRIPT_CALL_PARAMETER) + callablesGenerator.createIrVariable( + parameter, + irScript, + givenOrigin = IrDeclarationOrigin.SCRIPT_CALL_PARAMETER + ) } // NOTE: index should correspond to one generated in the collectTowerDataElementsForScript @@ -274,7 +278,7 @@ class Fir2IrVisitor( irBuiltIns.unitType, IrStatementOrigin.DESTRUCTURING_DECLARATION ).also { it.statements.add( - declarationStorage.createIrVariable(statement, conversionScope.parentFromStack()).also { + callablesGenerator.createIrVariable(statement, conversionScope.parentFromStack()).also { it.initializer = statement.initializer?.toIrStatement() as? IrExpression } ) @@ -392,7 +396,7 @@ class Fir2IrVisitor( override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: Any?): IrElement = whileAnalysing(session, simpleFunction) { val irFunction = if (simpleFunction.visibility == Visibilities.Local) { - declarationStorage.createIrFunction( + callablesGenerator.createIrFunction( simpleFunction, irParent = conversionScope.parent(), predefinedOrigin = IrDeclarationOrigin.LOCAL_FUNCTION, isLocal = true ) } else { @@ -414,7 +418,7 @@ class Fir2IrVisitor( data: Any? ): IrElement = whileAnalysing(session, anonymousFunction) { return anonymousFunction.convertWithOffsets { startOffset, endOffset -> - val irFunction = declarationStorage.createIrFunction( + val irFunction = callablesGenerator.createIrFunction( anonymousFunction, irParent = conversionScope.parent(), predefinedOrigin = IrDeclarationOrigin.LOCAL_FUNCTION, @@ -438,7 +442,7 @@ class Fir2IrVisitor( assert(variable.isLocal) val delegate = variable.delegate if (delegate != null) { - val irProperty = declarationStorage.createIrLocalDelegatedProperty(variable, conversionScope.parentFromStack()) + val irProperty = callablesGenerator.createIrLocalDelegatedProperty(variable, conversionScope.parentFromStack()) irProperty.delegate.initializer = convertToIrExpression(delegate, isDelegate = true) conversionScope.withFunction(irProperty.getter) { memberGenerator.convertFunctionContent(irProperty.getter, variable.getter, null) @@ -454,7 +458,7 @@ class Fir2IrVisitor( val isNextVariable = initializer is FirFunctionCall && initializer.calleeReference.toResolvedNamedFunctionSymbol()?.callableId?.isIteratorNext() == true && variable.source?.isChildOfForLoop == true - val irVariable = declarationStorage.createIrVariable( + val irVariable = callablesGenerator.createIrVariable( variable, conversionScope.parentFromStack(), if (isNextVariable) { if (variable.name.isSpecial && variable.name == SpecialNames.DESTRUCT) { @@ -1260,7 +1264,7 @@ class Fir2IrVisitor( return when { subjectVariable != null -> subjectVariable.accept(this, null) as IrVariable subjectExpression != null -> { - applyParentFromStackTo(declarationStorage.declareTemporaryVariable(convertToIrExpression(subjectExpression), "subject")) + applyParentFromStackTo(callablesGenerator.declareTemporaryVariable(convertToIrExpression(subjectExpression), "subject")) } else -> null } @@ -1419,7 +1423,7 @@ class Fir2IrVisitor( override fun visitCatch(catch: FirCatch, data: Any?): IrElement { return catch.convertWithOffsets { startOffset, endOffset -> - val catchParameter = declarationStorage.createIrVariable( + val catchParameter = callablesGenerator.createIrVariable( catch.parameter, conversionScope.parentFromStack(), IrDeclarationOrigin.CATCH_PARAMETER ) IrCatchImpl(startOffset, endOffset, catchParameter, catch.block.convertToIrBlock(forceUnitType = false)) 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 d89ac524d84..6a4159e44df 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 @@ -293,7 +293,7 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) : Fir2IrCompon isOperator: Boolean = false, ): IrFunction { val signature = if (klass.symbol.classId.isLocal) null else components.signatureComposer.composeSignature(syntheticCounterpart) - return components.declarationStorage.declareIrSimpleFunction(signature) { symbol -> + return components.callablesGenerator.declareIrSimpleFunction(signature) { symbol -> components.irFactory.createSimpleFunction( startOffset = UNDEFINED_OFFSET, endOffset = UNDEFINED_OFFSET, diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt index cfd0f9f9ded..ee66a1faf31 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt @@ -206,7 +206,7 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I delegateOverride: FirSimpleFunction ): IrSimpleFunction { val delegateFunction = - declarationStorage.createIrFunction( + callablesGenerator.createIrFunction( delegateOverride, subClass, predefinedOrigin = IrDeclarationOrigin.DELEGATED_MEMBER, fakeOverrideOwnerLookupTag = firSubClass.symbol.toLookupTag() ) @@ -297,7 +297,7 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I firDelegateProperty: FirProperty ): IrProperty { val delegateProperty = - declarationStorage.createIrProperty( + callablesGenerator.createIrProperty( firDelegateProperty, subClass, predefinedOrigin = IrDeclarationOrigin.DELEGATED_MEMBER, fakeOverrideOwnerLookupTag = firSubClass.symbol.toLookupTag() ) 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 171c04c6411..4efbf7b4ab6 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 @@ -122,7 +122,7 @@ class FakeOverrideGenerator( createFakeOverriddenIfNeeded( firClass, irClass, isLocal, functionSymbol, declarationStorage::getCachedIrFunction, - declarationStorage::createIrFunction, + callablesGenerator::createIrFunction, createFakeOverrideSymbol = { firFunction, callableSymbol -> val symbol = FirFakeOverrideGenerator.createSymbolForSubstitutionOverride(callableSymbol, firClass.symbol.classId) FirFakeOverrideGenerator.createSubstitutionOverrideFunction( @@ -150,7 +150,7 @@ class FakeOverrideGenerator( createFakeOverriddenIfNeeded( firClass, irClass, isLocal, propertyOrFieldSymbol, declarationStorage::getCachedIrProperty, - declarationStorage::createIrProperty, + callablesGenerator::createIrProperty, createFakeOverrideSymbol = { firProperty, callableSymbol -> val symbolForOverride = FirFakeOverrideGenerator.createSymbolForSubstitutionOverride(callableSymbol, firClass.symbol.classId) @@ -180,7 +180,7 @@ class FakeOverrideGenerator( firClass, irClass, isLocal, propertyOrFieldSymbol, { field, _, _ -> declarationStorage.getCachedIrFieldStaticFakeOverrideByDeclaration(field) }, { field, irParent, _, _ -> - declarationStorage.createIrField(field, irParent) + callablesGenerator.createIrField(field, irParent) }, createFakeOverrideSymbol = { firField, _ -> FirFakeOverrideGenerator.createSubstitutionOverrideField( 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 new file mode 100644 index 00000000000..94688cce164 --- /dev/null +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt @@ -0,0 +1,1020 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.backend.generators + +import com.intellij.openapi.progress.ProcessCanceledException +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.fir.* +import org.jetbrains.kotlin.fir.backend.* +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter +import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter +import org.jetbrains.kotlin.fir.declarations.utils.* +import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor +import org.jetbrains.kotlin.fir.descriptors.FirPackageFragmentDescriptor +import org.jetbrains.kotlin.fir.expressions.FirConstExpression +import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression +import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub +import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass +import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty +import org.jetbrains.kotlin.fir.references.toResolvedBaseSymbol +import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isLocalClassOrAnonymousObject +import org.jetbrains.kotlin.fir.resolve.isKFunctionInvoke +import org.jetbrains.kotlin.fir.symbols.* +import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.builders.declarations.UNDEFINED_PARAMETER_INDEX +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol +import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.impl.* +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.NameUtils +import org.jetbrains.kotlin.name.SpecialNames +import org.jetbrains.kotlin.types.AbstractTypeChecker +import org.jetbrains.kotlin.utils.addToStdlib.runUnless +import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment + +class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fir2IrComponents by components { + internal fun createExternalPackageFragment(fqName: FqName, moduleDescriptor: FirModuleDescriptor): IrExternalPackageFragment { + return createExternalPackageFragment(FirPackageFragmentDescriptor(fqName, moduleDescriptor)) + } + + internal fun createExternalPackageFragment(packageFragmentDescriptor: PackageFragmentDescriptor): IrExternalPackageFragment { + val symbol = IrExternalPackageFragmentSymbolImpl(packageFragmentDescriptor) + return IrExternalPackageFragmentImpl(symbol, packageFragmentDescriptor.fqName) + } + + /** + * [firCallable] is function or property (if [irFunction] is a property accessor) for + * which [irFunction] was build + * + * It is needed to determine proper dispatch receiver type if this declaration is fake-override + */ + private fun computeDispatchReceiverType( + irFunction: IrSimpleFunction, + firCallable: FirCallableDeclaration?, + parent: IrDeclarationParent?, + ): IrType? { + /* + * If some function is not fake-override, then its type should be just + * default type of containing class + * For fake overrides the default type calculated in the following way: + * 1. Find first overridden function, which is not fake override + * 2. Take its containing class + * 3. Find supertype of current containing class with type constructor of + * class from step 2 + */ + if (firCallable is FirProperty && firCallable.isLocal) return null + val containingClass = computeContainingClass(parent) ?: return null + val defaultType = containingClass.defaultType + if (firCallable == null) return defaultType + if (irFunction.origin != IrDeclarationOrigin.FAKE_OVERRIDE) return defaultType + + val originalCallable = firCallable.unwrapFakeOverrides() + val containerOfOriginalCallable = originalCallable.containingClassLookupTag() ?: return defaultType + val containerOfFakeOverride = firCallable.dispatchReceiverType ?: return defaultType + val correspondingSupertype = AbstractTypeChecker.findCorrespondingSupertypes( + session.typeContext.newTypeCheckerState(errorTypesEqualToAnything = false, stubTypesEqualToAnything = false), + containerOfFakeOverride, + containerOfOriginalCallable + ).firstOrNull() as ConeKotlinType? ?: return defaultType + return correspondingSupertype.toIrType() + } + + private fun computeContainingClass(parent: IrDeclarationParent?): IrClass? { + return if (parent is IrClass && parent !is Fir2IrDeclarationStorage.NonCachedSourceFileFacadeClass) { + parent + } else { + null + } + } + + fun setAndModifyParent(declaration: IrDeclaration, irParent: IrDeclarationParent?) { + if (irParent != null) { + declaration.parent = irParent + if (irParent is IrExternalPackageFragment) { + irParent.declarations += declaration + } + } + } + + private fun T.declareDefaultSetterParameter(type: IrType, firValueParameter: FirValueParameter?): T { + valueParameters = listOf( + createDefaultSetterParameter(startOffset, endOffset, type, parent = this, firValueParameter) + ) + return this + } + + internal fun createDefaultSetterParameter( + startOffset: Int, + endOffset: Int, + type: IrType, + parent: IrFunction, + firValueParameter: FirValueParameter?, + name: Name? = null, + isCrossinline: Boolean = false, + isNoinline: Boolean = false, + ): IrValueParameter { + return irFactory.createValueParameter( + startOffset = startOffset, + endOffset = endOffset, + origin = IrDeclarationOrigin.DEFINED, + name = name ?: SpecialNames.IMPLICIT_SET_PARAMETER, + type = type, + isAssignable = false, + symbol = IrValueParameterSymbolImpl(), + index = parent.contextReceiverParametersCount, + varargElementType = null, + isCrossinline = isCrossinline, + isNoinline = isNoinline, + isHidden = false, + ).apply { + this.parent = parent + if (firValueParameter != null) { + annotationGenerator.generate(this, firValueParameter) + } + } + } + + fun addContextReceiverParametersTo( + contextReceivers: List, + parent: IrFunction, + result: MutableList, + ) { + contextReceivers.mapIndexedTo(result) { index, contextReceiver -> + createIrParameterFromContextReceiver(contextReceiver, index).apply { + this.parent = parent + } + } + } + + /* + * In perfect world dispatchReceiverType should always be the default type of containing class + * But fake-overrides for members from Any have special rules for type of dispatch receiver + */ + private fun IrFunction.declareParameters( + function: FirFunction?, + irParent: IrDeclarationParent?, + dispatchReceiverType: IrType?, // has no sense for constructors + isStatic: Boolean, + forSetter: Boolean, + // Can be not-null only for property accessors + parentPropertyReceiver: FirReceiverParameter? = null + ) { + val containingClass = computeContainingClass(irParent) + val parent = this + if (function is FirSimpleFunction || function is FirConstructor) { + with(classifierStorage) { + setTypeParameters(function) + } + } + val typeOrigin = if (forSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT + if (function is FirDefaultPropertySetter) { + val valueParameter = function.valueParameters.first() + val type = valueParameter.returnTypeRef.toIrType(ConversionTypeOrigin.SETTER) + declareDefaultSetterParameter(type, valueParameter) + } else if (function != null) { + val contextReceivers = function.contextReceiversForFunctionOrContainingProperty() + + contextReceiverParametersCount = contextReceivers.size + valueParameters = buildList { + addContextReceiverParametersTo(contextReceivers, parent, this) + + function.valueParameters.mapIndexedTo(this) { index, valueParameter -> + createIrParameter( + valueParameter, index + contextReceiverParametersCount, + useStubForDefaultValueStub = function !is FirConstructor || containingClass?.name != Name.identifier("Enum"), + typeOrigin, + skipDefaultParameter = isFakeOverride || origin == IrDeclarationOrigin.DELEGATED_MEMBER + ).apply { + this.parent = parent + } + } + } + } + + val thisOrigin = IrDeclarationOrigin.DEFINED + if (function !is FirConstructor) { + val receiver: FirReceiverParameter? = + if (function !is FirPropertyAccessor && function != null) function.receiverParameter + else parentPropertyReceiver + if (receiver != null) { + extensionReceiverParameter = receiver.convertWithOffsets { startOffset, endOffset -> + val name = (function as? FirAnonymousFunction)?.label?.name?.let { + val suffix = it.takeIf(Name::isValidIdentifier) ?: "\$receiver" + Name.identifier("\$this\$$suffix") + } ?: SpecialNames.THIS + declareThisReceiverParameter( + thisType = receiver.typeRef.toIrType(typeOrigin), + thisOrigin = thisOrigin, + startOffset = startOffset, + endOffset = endOffset, + name = name, + explicitReceiver = receiver, + ) + } + } + // See [LocalDeclarationsLowering]: "local function must not have dispatch receiver." + val isLocal = function is FirSimpleFunction && function.isLocal + if (function !is FirAnonymousFunction && dispatchReceiverType != null && !isStatic && !isLocal) { + dispatchReceiverParameter = declareThisReceiverParameter( + thisType = dispatchReceiverType, + thisOrigin = thisOrigin + ) + } + } else { + // Set dispatch receiver parameter for inner class's constructor. + val outerClass = containingClass?.parentClassOrNull + if (containingClass?.isInner == true && outerClass != null) { + dispatchReceiverParameter = declareThisReceiverParameter( + thisType = outerClass.thisReceiver!!.type, + thisOrigin = thisOrigin + ) + } + } + } + + internal fun declareIrSimpleFunction( + signature: IdSignature?, + factory: (IrSimpleFunctionSymbol) -> IrSimpleFunction + ): IrSimpleFunction = + if (signature == null) { + factory(IrSimpleFunctionSymbolImpl()) + } else { + symbolTable.declareSimpleFunction(signature, { Fir2IrSimpleFunctionSymbol(signature) }, factory) + } + + fun createIrFunction( + function: FirFunction, + irParent: IrDeclarationParent?, + predefinedOrigin: IrDeclarationOrigin? = null, + isLocal: Boolean = false, + fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null, + ): IrSimpleFunction = convertCatching(function) { + val simpleFunction = function as? FirSimpleFunction + val isLambda = function is FirAnonymousFunction && function.isLambda + val updatedOrigin = when { + isLambda -> IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA + function.symbol.callableId.isKFunctionInvoke() -> IrDeclarationOrigin.FAKE_OVERRIDE + simpleFunction?.isStatic == true && simpleFunction.name in Fir2IrDeclarationStorage.ENUM_SYNTHETIC_NAMES -> IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER + + // Kotlin built-in class and Java originated method (Collection.forEach, etc.) + // It's necessary to understand that such methods do not belong to DefaultImpls but actually generated as default + // See org.jetbrains.kotlin.backend.jvm.lower.InheritedDefaultMethodsOnClassesLoweringKt.isDefinitelyNotDefaultImplsMethod + (irParent as? IrClass)?.origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB && + function.isJavaOrEnhancement -> IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB + else -> function.computeIrOrigin(predefinedOrigin) + } + // 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 && irParent !is Fir2IrLazyClass && + function.dispatchReceiverType?.isPrimitive != true && function.containerSource == null && + updatedOrigin != IrDeclarationOrigin.FAKE_OVERRIDE && !function.isOverride + ) { + signatureComposer.composeSignature(function, fakeOverrideOwnerLookupTag) + } + if (irParent is Fir2IrLazyClass && signature != null) { + // For private functions signature is null, fallback to non-lazy function + return lazyDeclarationsGenerator.createIrLazyFunction(function as FirSimpleFunction, signature, irParent, updatedOrigin) + } + val name = simpleFunction?.name + ?: if (isLambda) SpecialNames.ANONYMOUS else SpecialNames.NO_NAME_PROVIDED + val visibility = simpleFunction?.visibility ?: Visibilities.Local + val isSuspend = + if (isLambda) ((function as FirAnonymousFunction).typeRef as? FirResolvedTypeRef)?.type?.isSuspendOrKSuspendFunctionType(session) == true + else function.isSuspend + val created = function.convertWithOffsets { startOffset, endOffset -> + val result = 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) + enterScope(this.symbol) + setAndModifyParent(this, irParent) + declareParameters( + function, irParent, + dispatchReceiverType = computeDispatchReceiverType(this, simpleFunction, irParent), + isStatic = simpleFunction?.isStatic == true, + forSetter = false, + ) + convertAnnotationsForNonDeclaredMembers(function, origin) + leaveScope(this.symbol) + } + } + result + } + + if (visibility == Visibilities.Local) { + localStorage.putLocalFunction(function, created) + return created + } + if (function.symbol.callableId.isKFunctionInvoke()) { + (function.symbol.originalForSubstitutionOverride as? FirNamedFunctionSymbol)?.let { + created.overriddenSymbols += declarationStorage.getIrFunctionSymbol(it) as IrSimpleFunctionSymbol + } + } + if (function.isFakeOverride(fakeOverrideOwnerLookupTag)) { + val originalFunction = function.unwrapFakeOverrides() + val key = Fir2IrDeclarationStorage.FakeOverrideIdentifier( + originalFunction.symbol, + fakeOverrideOwnerLookupTag ?: function.containingClassLookupTag()!! + ) + irFakeOverridesForFirFakeOverrideMap[key] = created + } else { + functionCache[function] = created + } + return created + } + + fun createIrAnonymousInitializer( + anonymousInitializer: FirAnonymousInitializer, + irParent: IrClass + ): IrAnonymousInitializer = convertCatching(anonymousInitializer) { + return anonymousInitializer.convertWithOffsets { startOffset, endOffset -> + symbolTable.descriptorExtension.declareAnonymousInitializer( + startOffset, + endOffset, + IrDeclarationOrigin.DEFINED, + irParent.descriptor + ).apply { + this.parent = irParent + initializerCache[anonymousInitializer] = this + } + } + } + + private fun declareIrConstructor(signature: IdSignature?, factory: (IrConstructorSymbol) -> IrConstructor): IrConstructor = + if (signature == null) + factory(IrConstructorSymbolImpl()) + else + symbolTable.declareConstructor(signature, { Fir2IrConstructorSymbol(signature) }, factory) + + + fun createIrConstructor( + constructor: FirConstructor, + irParent: IrClass, + predefinedOrigin: IrDeclarationOrigin? = null, + isLocal: Boolean = false, + ): IrConstructor = convertCatching(constructor) { + val origin = constructor.computeIrOrigin(predefinedOrigin) + val isPrimary = constructor.isPrimary + val signature = + runUnless(isLocal || !configuration.linkViaSignatures) { + signatureComposer.composeSignature(constructor) + } + val visibility = if (irParent.isAnonymousObject) Visibilities.Public else constructor.visibility + return constructor.convertWithOffsets { startOffset, endOffset -> + declareIrConstructor(signature) { symbol -> + classifierStorage.preCacheTypeParameters(constructor, symbol) + irFactory.createConstructor( + startOffset = startOffset, + endOffset = endOffset, + origin = origin, + name = SpecialNames.INIT, + visibility = components.visibilityConverter.convertToDescriptorVisibility(visibility), + isInline = false, + isExpect = constructor.isExpect, + returnType = constructor.returnTypeRef.toIrType(), + symbol = symbol, + isPrimary = isPrimary, + isExternal = false, + ).apply { + metadata = FirMetadataSource.Function(constructor) + // Add to cache before generating parameters to prevent an infinite loop when an annotation value parameter is annotated + // with the annotation itself. + constructorCache[constructor] = this + enterScope(this.symbol) + setAndModifyParent(this, irParent) + declareParameters(constructor, irParent, dispatchReceiverType = null, isStatic = false, forSetter = false) + leaveScope(this.symbol) + } + } + } + } + + private fun declareIrAccessor( + signature: IdSignature?, + factory: (IrSimpleFunctionSymbol) -> IrSimpleFunction + ): IrSimpleFunction = + if (signature == null) + factory(IrSimpleFunctionSymbolImpl()) + else + symbolTable.declareSimpleFunction(signature, { Fir2IrSimpleFunctionSymbol(signature) }, factory) + + private fun createIrPropertyAccessor( + propertyAccessor: FirPropertyAccessor?, + property: FirProperty, + correspondingProperty: IrDeclarationWithName, + propertyType: IrType, + irParent: IrDeclarationParent?, + isSetter: Boolean, + origin: IrDeclarationOrigin, + startOffset: Int, + endOffset: Int, + dontUseSignature: Boolean = false, + fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null, + propertyAccessorForAnnotations: FirPropertyAccessor? = propertyAccessor, + ): IrSimpleFunction = convertCatching(propertyAccessor ?: property) { + val prefix = if (isSetter) "set" else "get" + val signature = + runUnless(dontUseSignature) { + signatureComposer.composeAccessorSignature(property, isSetter, fakeOverrideOwnerLookupTag) + } + val containerSource = (correspondingProperty as? IrProperty)?.containerSource + return declareIrAccessor( + signature + ) { symbol -> + val accessorReturnType = if (isSetter) irBuiltIns.unitType else propertyType + val visibility = propertyAccessor?.visibility?.let { + components.visibilityConverter.convertToDescriptorVisibility(it) + } + irFactory.createSimpleFunction( + startOffset = startOffset, + endOffset = endOffset, + origin = origin, + name = Name.special("<$prefix-${correspondingProperty.name}>"), + visibility = visibility ?: (correspondingProperty as IrDeclarationWithVisibility).visibility, + isInline = propertyAccessor?.isInline == true, + isExpect = false, + returnType = accessorReturnType, + modality = (correspondingProperty as? IrOverridableMember)?.modality ?: Modality.FINAL, + symbol = symbol, + isTailrec = false, + isSuspend = false, + isOperator = false, + isInfix = false, + isExternal = propertyAccessor?.isExternal == true, + containerSource = containerSource, + ).apply { + correspondingPropertySymbol = (correspondingProperty as? IrProperty)?.symbol + if (propertyAccessor != null) { + metadata = FirMetadataSource.Function(propertyAccessor) + // Note that deserialized annotations are stored in the accessor, not the property. + convertAnnotationsForNonDeclaredMembers(propertyAccessor, origin) + } + + if (propertyAccessorForAnnotations != null) { + convertAnnotationsForNonDeclaredMembers(propertyAccessorForAnnotations, origin) + } + with(classifierStorage) { + setTypeParameters( + property, if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT + ) + } + // NB: we should enter accessor' scope before declaring its parameters + // (both setter default and receiver ones, if any) + enterScope(this.symbol) + if (propertyAccessor == null && isSetter) { + declareDefaultSetterParameter( + property.returnTypeRef.toIrType(ConversionTypeOrigin.SETTER), + firValueParameter = null + ) + } + setAndModifyParent(this, irParent) + val dispatchReceiverType = computeDispatchReceiverType(this, property, irParent) + declareParameters( + propertyAccessor, irParent, dispatchReceiverType, + isStatic = irParent !is IrClass || propertyAccessor?.isStatic == true, forSetter = isSetter, + parentPropertyReceiver = property.receiverParameter, + ) + leaveScope(this.symbol) + if (correspondingProperty is Fir2IrLazyProperty && correspondingProperty.containingClass != null && !isFakeOverride && dispatchReceiverType != null) { + this.overriddenSymbols = correspondingProperty.fir.generateOverriddenAccessorSymbols( + correspondingProperty.containingClass, !isSetter + ) + } + } + } + } + + internal fun createBackingField( + irProperty: IrProperty, + firProperty: FirProperty, + origin: IrDeclarationOrigin, + visibility: DescriptorVisibility, + name: Name, + isFinal: Boolean, + firInitializerExpression: FirExpression?, + type: IrType? = null + ): IrField = convertCatching(firProperty) { + val inferredType = type ?: firInitializerExpression!!.resolvedType.toIrType() + return declareIrField { symbol -> + irFactory.createField( + startOffset = irProperty.startOffset, + endOffset = irProperty.endOffset, + origin = origin, + name = name, + visibility = visibility, + symbol = symbol, + type = inferredType, + isFinal = isFinal, + isStatic = firProperty.isStatic || !(irProperty.parent is IrClass || irProperty.parent is IrScript), + isExternal = firProperty.isExternal, + ).also { + it.correspondingPropertySymbol = irProperty.symbol + }.apply { + metadata = FirMetadataSource.Property(firProperty) + convertAnnotationsForNonDeclaredMembers(firProperty, origin) + } + } + } + + private val FirProperty.fieldVisibility: Visibility + get() = when { + hasExplicitBackingField -> backingField?.visibility ?: status.visibility + isLateInit -> setter?.visibility ?: status.visibility + isConst -> status.visibility + hasJvmFieldAnnotation(session) -> status.visibility + origin == FirDeclarationOrigin.ScriptCustomization.ResultProperty -> status.visibility + else -> Visibilities.Private + } + + private fun declareIrProperty( + signature: IdSignature?, + factory: (IrPropertySymbol) -> IrProperty + ): IrProperty = + if (signature == null) + factory(IrPropertySymbolImpl()) + else + symbolTable.declareProperty(signature, { Fir2IrPropertySymbol(signature) }, factory) + + private fun declareIrField(factory: (IrFieldSymbol) -> IrField): IrField = + factory(IrFieldSymbolImpl()) + + fun createIrProperty( + property: FirProperty, + irParent: IrDeclarationParent?, + predefinedOrigin: IrDeclarationOrigin? = null, + isLocal: Boolean = false, + fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null, + ): IrProperty = convertCatching(property) { + val origin = + if (property.isStatic && property.name in Fir2IrDeclarationStorage.ENUM_SYNTHETIC_NAMES) IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER + else property.computeIrOrigin(predefinedOrigin) + // See similar comments in createIrFunction above + val signature = + runUnless( + isLocal || + !configuration.linkViaSignatures && irParent !is Fir2IrLazyClass && + property.dispatchReceiverType?.isPrimitive != true && property.containerSource == null && + origin != IrDeclarationOrigin.FAKE_OVERRIDE && !property.isOverride + ) { + signatureComposer.composeSignature(property, fakeOverrideOwnerLookupTag) + } + if (irParent is Fir2IrLazyClass && signature != null) { + // For private functions signature is null, fallback to non-lazy property + return lazyDeclarationsGenerator.createIrLazyProperty(property, signature, irParent, origin) + } + return property.convertWithOffsets { startOffset, endOffset -> + val result = declareIrProperty(signature) { symbol -> + classifierStorage.preCacheTypeParameters(property, symbol) + irFactory.createProperty( + startOffset = startOffset, + endOffset = endOffset, + origin = origin, + name = property.name, + visibility = components.visibilityConverter.convertToDescriptorVisibility(property.visibility), + modality = property.modality!!, + symbol = symbol, + isVar = property.isVar, + isConst = property.isConst, + isLateinit = property.isLateInit, + isDelegated = property.delegate != null, + isExternal = property.isExternal, + containerSource = property.containerSource, + isExpect = property.isExpect, + ).apply { + metadata = FirMetadataSource.Property(property) + convertAnnotationsForNonDeclaredMembers(property, origin) + enterScope(this.symbol) + if (irParent != null) { + parent = irParent + } + val type = property.returnTypeRef.toIrType() + val delegate = property.delegate + val getter = property.getter + val setter = property.setter + if (delegate != null || property.hasBackingField) { + val backingField = if (delegate != null) { + ((delegate as? FirQualifiedAccessExpression)?.calleeReference?.toResolvedBaseSymbol()?.fir as? FirTypeParameterRefsOwner)?.let { + classifierStorage.preCacheTypeParameters(it, symbol) + } + createBackingField( + this, + property, + IrDeclarationOrigin.PROPERTY_DELEGATE, + components.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility), + NameUtils.propertyDelegateName(property.name), + true, + delegate + ) + } else { + val initializer = getEffectivePropertyInitializer(property, resolveIfNeeded = true) + // There are cases when we get here for properties + // that have no backing field. For example, in the + // funExpression.kt test there's an attempt + // to access the `javaClass` property of the `foo0`'s + // `block` argument + val typeToUse = property.backingField?.returnTypeRef?.toIrType() ?: type + createBackingField( + this, + property, + IrDeclarationOrigin.PROPERTY_BACKING_FIELD, + components.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility), + property.name, + property.isVal, + initializer, + typeToUse + ).also { field -> + if (initializer is FirConstExpression<*>) { + val constType = initializer.resolvedType.toIrType() + field.initializer = factory.createExpressionBody(initializer.toIrConst(constType)) + } + } + } + backingField.symbol.let { + backingFieldForPropertyCache[symbol] = it + propertyForBackingFieldCache[it] = symbol + } + this.backingField = backingField + } + if (irParent != null) { + backingField?.parent = irParent + } + this.getter = createIrPropertyAccessor( + getter, property, this, type, irParent, false, + when { + origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin + origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER -> origin + delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR + origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin + origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin + getter == null || getter is FirDefaultPropertyGetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR + else -> origin + }, + startOffset, endOffset, + dontUseSignature = signature == null, fakeOverrideOwnerLookupTag, + property.unwrapFakeOverrides().getter, + ).also { + getterForPropertyCache[symbol] = it.symbol + } + if (property.isVar) { + this.setter = createIrPropertyAccessor( + setter, property, this, type, irParent, true, + when { + delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR + origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin + origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin + setter is FirDefaultPropertySetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR + else -> origin + }, + startOffset, endOffset, + dontUseSignature = signature == null, fakeOverrideOwnerLookupTag, + property.unwrapFakeOverrides().setter, + ).also { + setterForPropertyCache[symbol] = it.symbol + } + } + leaveScope(this.symbol) + } + } + if (property.isFakeOverride(fakeOverrideOwnerLookupTag)) { + val originalProperty = property.unwrapFakeOverrides() + val key = Fir2IrDeclarationStorage.FakeOverrideIdentifier( + originalProperty.symbol, + fakeOverrideOwnerLookupTag ?: property.containingClassLookupTag()!! + ) + irFakeOverridesForFirFakeOverrideMap[key] = result + } else { + propertyCache[property] = result + } + result + } + } + + /** + * In partial module compilation (see [org.jetbrains.kotlin.analysis.api.fir.components.KtFirCompilerFacility]), + * referenced properties might be resolved only up to [FirResolvePhase.CONTRACTS], + * however the backend requires the exact initializer type. + */ + private fun getEffectivePropertyInitializer(property: FirProperty, resolveIfNeeded: Boolean): FirExpression? { + val initializer = property.backingField?.initializer ?: property.initializer + + if (resolveIfNeeded && initializer is FirConstExpression<*>) { + property.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE) + return getEffectivePropertyInitializer(property, resolveIfNeeded = false) + } + + return initializer + } + + fun createIrFieldAndDelegatedMembers(field: FirField, owner: FirClass, irClass: IrClass): IrField? { + // Either take a corresponding constructor property backing field, + // or create a separate delegate field + val irField = declarationStorage.getOrCreateDelegateIrField(field, owner, irClass) + delegatedMemberGenerator.generate(irField, field, owner, irClass) + if (owner.isLocalClassOrAnonymousObject()) { + delegatedMemberGenerator.generateBodies() + } + // If it's a property backing field, it should not be added to the class in Fir2IrConverter, so it's not returned + return irField.takeIf { it.correspondingPropertySymbol == null } + } + + internal fun createIrField( + field: FirField, + irParent: IrDeclarationParent?, + type: ConeKotlinType = field.returnTypeRef.coneType, + origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB + ): IrField = convertCatching(field) { + val irType = type.toIrType() + val classId = (irParent as? IrClass)?.classId + val containingClassLookupTag = classId?.toLookupTag() + val signature = signatureComposer.composeSignature(field, containingClassLookupTag) + return field.convertWithOffsets { startOffset, endOffset -> + if (signature != null) { + symbolTable.declareField( + signature, symbolFactory = { IrFieldPublicSymbolImpl(signature) } + ) { symbol -> + irFactory.createField( + startOffset = startOffset, + endOffset = endOffset, + origin = origin, + name = field.name, + visibility = components.visibilityConverter.convertToDescriptorVisibility(field.visibility), + symbol = symbol, + type = irType, + isFinal = field.modality == Modality.FINAL, + isStatic = field.isStatic, + isExternal = false + ) + } + } else { + irFactory.createField( + startOffset = startOffset, + endOffset = endOffset, + origin = origin, + name = field.name, + visibility = components.visibilityConverter.convertToDescriptorVisibility(field.visibility), + symbol = IrFieldSymbolImpl(), + type = irType, + isFinal = field.modality == Modality.FINAL, + isStatic = field.isStatic, + isExternal = false + ) + }.apply { + metadata = FirMetadataSource.Field(field) + val staticFakeOverrideKey = getFieldStaticFakeOverrideKey(field, containingClassLookupTag) + if (staticFakeOverrideKey == null) { + fieldCache[field] = this + } else { + fieldStaticOverrideCache[staticFakeOverrideKey] = this + } + val initializer = field.unwrapFakeOverrides().initializer + if (initializer is FirConstExpression<*>) { + this.initializer = factory.createExpressionBody(initializer.toIrConst(irType)) + } + setAndModifyParent(this, irParent) + } + } + } + + internal fun createIrParameter( + valueParameter: FirValueParameter, + index: Int = UNDEFINED_PARAMETER_INDEX, + useStubForDefaultValueStub: Boolean = true, + typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT, + skipDefaultParameter: Boolean = false, + // Use this parameter if you want to insert the actual default value instead of the stub (overrides useStubForDefaultValueStub parameter). + // This parameter is intended to be used for default values of annotation parameters where they are needed and + // may produce incorrect results for values that may be encountered outside annotations. + // Does not do anything if valueParameter.defaultValue is already FirExpressionStub. + forcedDefaultValueConversion: Boolean = false, + ): IrValueParameter = convertCatching(valueParameter) { + val origin = valueParameter.computeIrOrigin() + val type = valueParameter.returnTypeRef.toIrType(typeOrigin) + val irParameter = valueParameter.convertWithOffsets { startOffset, endOffset -> + irFactory.createValueParameter( + startOffset = startOffset, + endOffset = endOffset, + origin = origin, + name = valueParameter.name, + type = type, + isAssignable = false, + symbol = IrValueParameterSymbolImpl(), + index = index, + varargElementType = valueParameter.varargElementType?.toIrType(typeOrigin), + isCrossinline = valueParameter.isCrossinline, + isNoinline = valueParameter.isNoinline, + isHidden = false, + ).apply { + val defaultValue = valueParameter.defaultValue + if (!skipDefaultParameter && defaultValue != null) { + this.defaultValue = when { + forcedDefaultValueConversion && defaultValue !is FirExpressionStub -> + defaultValue.asCompileTimeIrInitializer(components) + useStubForDefaultValueStub || defaultValue !is FirExpressionStub -> + factory.createExpressionBody( + IrErrorExpressionImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, + "Stub expression for default value of ${valueParameter.name}" + ) + ) + else -> null + } + } + annotationGenerator.generate(this, valueParameter) + } + } + localStorage.putParameter(valueParameter, irParameter) + return irParameter + } + + private fun createIrParameterFromContextReceiver( + contextReceiver: FirContextReceiver, + index: Int, + ): IrValueParameter = convertCatching(contextReceiver) { + val type = contextReceiver.typeRef.toIrType() + return contextReceiver.convertWithOffsets { startOffset, endOffset -> + irFactory.createValueParameter( + startOffset = startOffset, + endOffset = endOffset, + origin = IrDeclarationOrigin.DEFINED, + name = NameUtils.contextReceiverName(index), + type = type, + isAssignable = false, + symbol = IrValueParameterSymbolImpl(), + index = index, + varargElementType = null, + isCrossinline = false, + isNoinline = false, + isHidden = false, + ) + } + } + + // TODO: KT-58686 + private var lastTemporaryIndex: Int = 0 + private fun nextTemporaryIndex(): Int = lastTemporaryIndex++ + + private fun getNameForTemporary(nameHint: String?): String { + val index = nextTemporaryIndex() + return if (nameHint != null) "tmp${index}_$nameHint" else "tmp$index" + } + + private fun declareIrVariable( + startOffset: Int, endOffset: Int, + origin: IrDeclarationOrigin, name: Name, type: IrType, + isVar: Boolean, isConst: Boolean, isLateinit: Boolean + ): IrVariable = + IrVariableImpl( + startOffset, endOffset, origin, IrVariableSymbolImpl(), name, type, + isVar, isConst, isLateinit + ) + + fun createIrVariable( + variable: FirVariable, + irParent: IrDeclarationParent, + givenOrigin: IrDeclarationOrigin? = null + ): IrVariable = convertCatching(variable) { + val type = variable.irTypeForPotentiallyComponentCall() + // Some temporary variables are produced in RawFirBuilder, but we consistently use special names for them. + val origin = when { + givenOrigin != null -> givenOrigin + variable.name == SpecialNames.ITERATOR -> IrDeclarationOrigin.FOR_LOOP_ITERATOR + variable.name.isSpecial -> IrDeclarationOrigin.IR_TEMPORARY_VARIABLE + else -> IrDeclarationOrigin.DEFINED + } + val isLateInit = if (variable is FirProperty) variable.isLateInit else false + val irVariable = variable.convertWithOffsets { startOffset, endOffset -> + declareIrVariable( + startOffset, endOffset, origin, + variable.name, type, variable.isVar, isConst = false, isLateinit = isLateInit + ) + } + irVariable.parent = irParent + localStorage.putVariable(variable, irVariable) + return irVariable + } + + fun createIrLocalDelegatedProperty( + property: FirProperty, + irParent: IrDeclarationParent + ): IrLocalDelegatedProperty = convertCatching(property) { + val type = property.returnTypeRef.toIrType() + val origin = IrDeclarationOrigin.DEFINED + val symbol = IrLocalDelegatedPropertySymbolImpl() + val irProperty = property.convertWithOffsets { startOffset, endOffset -> + irFactory.createLocalDelegatedProperty( + startOffset = startOffset, + endOffset = endOffset, + origin = origin, + name = property.name, + symbol = symbol, + type = type, + isVar = property.isVar + ) + }.apply { + parent = irParent + metadata = FirMetadataSource.Property(property) + enterScope(this.symbol) + delegate = declareIrVariable( + startOffset, endOffset, IrDeclarationOrigin.PROPERTY_DELEGATE, + NameUtils.propertyDelegateName(property.name), property.delegate!!.resolvedType.toIrType(), + isVar = false, isConst = false, isLateinit = false + ).also { + delegateVariableForPropertyCache[symbol] = it.symbol + } + delegate.parent = irParent + getter = createIrPropertyAccessor( + property.getter, property, this, type, irParent, false, + IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, startOffset, endOffset, dontUseSignature = true + ).also { + getterForPropertyCache[symbol] = it.symbol + } + if (property.isVar) { + setter = createIrPropertyAccessor( + property.setter, property, this, type, irParent, true, + IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, startOffset, endOffset, dontUseSignature = true + ).also { + setterForPropertyCache[symbol] = it.symbol + } + } + annotationGenerator.generate(this, property) + leaveScope(this.symbol) + } + localStorage.putDelegatedProperty(property, irProperty) + return irProperty + } + + fun declareTemporaryVariable(base: IrExpression, nameHint: String? = null): IrVariable { + return declareIrVariable( + base.startOffset, base.endOffset, IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, + Name.identifier(getNameForTemporary(nameHint)), base.type, + isVar = false, isConst = false, isLateinit = false + ).apply { + initializer = base + } + } + + private fun IrMutableAnnotationContainer.convertAnnotationsForNonDeclaredMembers( + firAnnotationContainer: FirAnnotationContainer, origin: IrDeclarationOrigin, + ) { + if ((firAnnotationContainer as? FirDeclaration)?.let { it.isFromLibrary || it.isPrecompiled } == true + || origin == IrDeclarationOrigin.FAKE_OVERRIDE + ) { + annotationGenerator.generate(this, firAnnotationContainer) + } + } + + private inline fun convertCatching(element: FirElement, block: () -> R): R { + try { + return block() + } catch (e: ProcessCanceledException) { + throw e + } catch (e: Exception) { + errorWithAttachment("Exception was thrown during transformation of ${element::class.java}", cause = e) { + withFirEntry("element", element) + } + } + } +} 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 new file mode 100644 index 00000000000..1bd5e56b8c9 --- /dev/null +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt @@ -0,0 +1,98 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.backend.generators + +import org.jetbrains.kotlin.fir.backend.Fir2IrComponents +import org.jetbrains.kotlin.fir.backend.convertWithOffsets +import org.jetbrains.kotlin.fir.backend.isStubPropertyForPureField +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.dispatchReceiverClassLookupTagOrNull +import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride +import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass +import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty +import org.jetbrains.kotlin.fir.lazy.Fir2IrLazySimpleFunction +import org.jetbrains.kotlin.fir.originalForSubstitutionOverride +import org.jetbrains.kotlin.fir.symbols.Fir2IrPropertySymbol +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent +import org.jetbrains.kotlin.ir.declarations.IrProperty +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.symbols.IrSymbolInternals +import org.jetbrains.kotlin.ir.util.IdSignature + +class Fir2IrLazyDeclarationsGenerator(val components: Fir2IrComponents) : Fir2IrComponents by components { + internal fun createIrLazyFunction( + fir: FirSimpleFunction, + signature: IdSignature, + lazyParent: IrDeclarationParent, + declarationOrigin: IrDeclarationOrigin + ): IrSimpleFunction { + val symbol = symbolTable.referenceSimpleFunction(signature) + val irFunction = fir.convertWithOffsets { startOffset, endOffset -> + symbolTable.declareSimpleFunction(signature, { symbol }) { + val isFakeOverride = fir.isSubstitutionOrIntersectionOverride + Fir2IrLazySimpleFunction( + components, startOffset, endOffset, declarationOrigin, + fir, (lazyParent as? Fir2IrLazyClass)?.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 + } + + @OptIn(IrSymbolInternals::class) + internal fun createIrLazyProperty( + fir: FirProperty, + signature: IdSignature, + lazyParent: IrDeclarationParent, + declarationOrigin: IrDeclarationOrigin + ): IrProperty { + val symbol = Fir2IrPropertySymbol(signature) + val firPropertySymbol = fir.symbol + + fun create(startOffset: Int, endOffset: Int): Fir2IrLazyProperty { + val isFakeOverride = + fir.isSubstitutionOrIntersectionOverride && + firPropertySymbol.dispatchReceiverClassLookupTagOrNull() != + firPropertySymbol.originalForSubstitutionOverride?.dispatchReceiverClassLookupTagOrNull() + return Fir2IrLazyProperty( + components, startOffset, endOffset, declarationOrigin, + fir, (lazyParent as? Fir2IrLazyClass)?.fir, symbol, isFakeOverride + ).apply { + this.parent = lazyParent + } + } + + val irProperty = fir.convertWithOffsets { startOffset, endOffset -> + if (fir.isStubPropertyForPureField == true) { + // Very special case when two similar properties can exist so conflicts in SymbolTable are possible. + // See javaCloseFieldAndKotlinProperty.kt in BB tests + symbolTable.declarePropertyWithSignature(signature, symbol) + create(startOffset, endOffset) + symbol.owner + } else { + symbolTable.declareProperty(signature, { symbol }) { + create(startOffset, endOffset) + } + } + } + propertyCache[fir] = irProperty + irProperty.getter?.symbol?.let { getterForPropertyCache[symbol] = it } + irProperty.setter?.symbol?.let { setterForPropertyCache[symbol] = it } + irProperty.backingField?.symbol?.let { + backingFieldForPropertyCache[symbol] = it + propertyForBackingFieldCache[it] = symbol + } + return irProperty + } + +} diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyConstructor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyConstructor.kt index 48a64a7d466..351117e9436 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyConstructor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyConstructor.kt @@ -102,17 +102,17 @@ class Fir2IrLazyConstructor( declarationStorage.enterScope(this.symbol) buildList { - declarationStorage.addContextReceiverParametersTo( + callablesGenerator.addContextReceiverParametersTo( fir.contextReceivers, this@Fir2IrLazyConstructor, - this@buildList, + this@buildList ) fir.valueParameters.mapIndexedTo(this) { index, valueParameter -> - declarationStorage.createIrParameter( + callablesGenerator.createIrParameter( valueParameter, index + contextReceiverParametersCount, useStubForDefaultValueStub = (parent as? IrClass)?.name != Name.identifier("Enum"), - forcedDefaultValueConversion = (parent as? IrClass)?.isAnnotationClass == true, + forcedDefaultValueConversion = (parent as? IrClass)?.isAnnotationClass == true ).apply { this.parent = this@Fir2IrLazyConstructor } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyProperty.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyProperty.kt index b9014635cc6..7fa2e10b8d7 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyProperty.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyProperty.kt @@ -115,7 +115,8 @@ class Fir2IrLazyProperty( } val initializer = fir.backingField?.initializer ?: fir.initializer val visibility = fir.backingField?.visibility ?: fir.visibility - createBackingField( + callablesGenerator.createBackingField( + this@Fir2IrLazyProperty, fir, IrDeclarationOrigin.PROPERTY_BACKING_FIELD, components.visibilityConverter.convertToDescriptorVisibility(visibility), @@ -130,9 +131,14 @@ class Fir2IrLazyProperty( } fir.hasBackingField && origin != IrDeclarationOrigin.FAKE_OVERRIDE -> { with(declarationStorage) { - createBackingField( - fir, IrDeclarationOrigin.PROPERTY_BACKING_FIELD, - components.visibilityConverter.convertToDescriptorVisibility(fir.visibility), fir.name, fir.isVal, fir.initializer, + callablesGenerator.createBackingField( + this@Fir2IrLazyProperty, + fir, + IrDeclarationOrigin.PROPERTY_BACKING_FIELD, + components.visibilityConverter.convertToDescriptorVisibility(fir.visibility), + fir.name, + fir.isVal, + fir.initializer, type ).also { field -> field.initializer = toIrInitializer(fir.initializer) @@ -141,10 +147,14 @@ class Fir2IrLazyProperty( } fir.delegate != null -> { with(declarationStorage) { - createBackingField( - fir, IrDeclarationOrigin.PROPERTY_DELEGATE, + callablesGenerator.createBackingField( + this@Fir2IrLazyProperty, + fir, + IrDeclarationOrigin.PROPERTY_DELEGATE, components.visibilityConverter.convertToDescriptorVisibility(fir.visibility), - NameUtils.propertyDelegateName(fir.name), true, fir.delegate + NameUtils.propertyDelegateName(fir.name), + true, + fir.delegate ) } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyPropertyAccessor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyPropertyAccessor.kt index da07ef1b821..af1fa9b20c2 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyPropertyAccessor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyPropertyAccessor.kt @@ -81,16 +81,16 @@ class Fir2IrLazyPropertyAccessor( declarationStorage.enterScope(this.symbol) buildList { - declarationStorage.addContextReceiverParametersTo( + callablesGenerator.addContextReceiverParametersTo( fir.contextReceiversForFunctionOrContainingProperty(), this@Fir2IrLazyPropertyAccessor, - this@buildList, + this@buildList ) if (isSetter) { val valueParameter = firAccessor?.valueParameters?.firstOrNull() add( - declarationStorage.createDefaultSetterParameter( + callablesGenerator.createDefaultSetterParameter( startOffset, endOffset, (valueParameter?.returnTypeRef ?: firParentProperty.returnTypeRef).toIrType( typeConverter, conversionTypeContext diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazySimpleFunction.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazySimpleFunction.kt index 5988da81731..0ec04c1ce09 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazySimpleFunction.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazySimpleFunction.kt @@ -69,14 +69,14 @@ class Fir2IrLazySimpleFunction( declarationStorage.enterScope(this.symbol) buildList { - declarationStorage.addContextReceiverParametersTo( + callablesGenerator.addContextReceiverParametersTo( fir.contextReceiversForFunctionOrContainingProperty(), this@Fir2IrLazySimpleFunction, - this@buildList, + this@buildList ) fir.valueParameters.mapIndexedTo(this) { index, valueParameter -> - declarationStorage.createIrParameter( + callablesGenerator.createIrParameter( valueParameter, index + contextReceiverParametersCount, skipDefaultParameter = isFakeOverride ).apply { this.parent = this@Fir2IrLazySimpleFunction