From c3e6dd12a2ed70453c99575cd48e47afc71c6488 Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Thu, 14 Dec 2023 16:45:32 +0100 Subject: [PATCH] [FIR] FirFakeOverrideGenerator: generate fake declaration with STATUS phase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The requirement for original declarations is to have resolved status, so we can set at least `STATUS` phase for copied ones. This fixes the problem that fake declarations for local declarations can have `RAW_FIR` phase due to the copy from the original declarations, as during body resolution all local declarations have only this phase. Another issue: we cannot set the phase from the original declaration as it is not guaranteed that we will have everything in the resolved state. E.g., we can have the original declaration in `BODY_RESOLVE` phase, but at the same time a containing class for fake declaration can be in `STATUS` phase, for example. This means that the fake declaration can have unresolved type annotation as it has them from both places – from the original declaration and from the class super type. To simplify the code, we can just always set STATUS phase to be sure that everything is resolved correctly. Also, so we can optimize the logic for all phases above on Low Level FIR level ^KT-64243 --- .../LLFirResolveMultiDesignationCollector.kt | 42 +-- .../LLFirAnnotationArgumentsLazyResolver.kt | 3 + .../LLFirContractsLazyResolver.kt | 4 + .../LLFirExpectActualMatcherLazyResolver.kt | 17 +- .../scopes/impl/FirFakeOverrideGenerator.kt | 301 +++++++++--------- .../fir/declarations/FirDeclarationOrigin.kt | 20 +- 6 files changed, 206 insertions(+), 181 deletions(-) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirResolveMultiDesignationCollector.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirResolveMultiDesignationCollector.kt index c1313b42926..74b77d7bc06 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirResolveMultiDesignationCollector.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirResolveMultiDesignationCollector.kt @@ -59,37 +59,27 @@ internal object LLFirResolveMultiDesignationCollector { else -> throwUnexpectedFirElementError(this) } - private fun FirDeclaration.shouldBeResolved(): Boolean = when (origin) { - is FirDeclarationOrigin.Source, - is FirDeclarationOrigin.ImportedFromObjectOrStatic, - is FirDeclarationOrigin.Delegated, - is FirDeclarationOrigin.Synthetic, - is FirDeclarationOrigin.SubstitutionOverride, - is FirDeclarationOrigin.SamConstructor, - is FirDeclarationOrigin.WrappedIntegerOperator, - is FirDeclarationOrigin.IntersectionOverride, - is FirDeclarationOrigin.ScriptCustomization, - -> { - when (this) { - is FirFile -> true - is FirSyntheticProperty, is FirSyntheticPropertyAccessor -> false - is FirSimpleFunction, - is FirProperty, - is FirPropertyAccessor, - is FirField, - is FirTypeAlias, - is FirConstructor, - -> true - else -> true - } - } - else -> { + private fun FirDeclaration.shouldBeResolved(): Boolean { + if (!origin.isLazyResolvable) { @OptIn(ResolveStateAccess::class) check(resolvePhase == FirResolvePhase.BODY_RESOLVE) { "Expected body resolve phase for origin $origin but found $resolveState" } - false + return false + } + + return when (this) { + is FirFile -> true + is FirSyntheticProperty, is FirSyntheticPropertyAccessor -> false + is FirSimpleFunction, + is FirProperty, + is FirPropertyAccessor, + is FirField, + is FirTypeAlias, + is FirConstructor, + -> true + else -> true } } } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentsLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentsLazyResolver.kt index 48b1a96b0ec..59bb8f3193d 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentsLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentsLazyResolver.kt @@ -153,6 +153,9 @@ private class LLFirAnnotationArgumentsTargetResolver( } override fun doLazyResolveUnderLock(target: FirElementWithResolveState) { + // There is no sense to resolve such declarations as they do not have their own annotations + if (target is FirCallableDeclaration && target.isCopyCreatedInScope) return + resolveWithKeeper( target, target.llFirSession, diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirContractsLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirContractsLazyResolver.kt index b747581fbef..cb3bdcaa0f6 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirContractsLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirContractsLazyResolver.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.contracts.FirRawContractDescription import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor +import org.jetbrains.kotlin.fir.isCopyCreatedInScope import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector @@ -64,6 +65,9 @@ private class LLFirContractsTargetResolver( override fun doLazyResolveUnderLock(target: FirElementWithResolveState) { collectTowerDataContext(target) + // There is no sense to resolve such declarations as they do not have contracts + if (target is FirCallableDeclaration && target.isCopyCreatedInScope) return + when (target) { is FirPrimaryConstructor, is FirErrorPrimaryConstructor -> { // No contracts here diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirExpectActualMatcherLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirExpectActualMatcherLazyResolver.kt index 1cb8a471f3b..d738eb108bc 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirExpectActualMatcherLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirExpectActualMatcherLazyResolver.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.FirElementWithResolveState import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.FirStatement +import org.jetbrains.kotlin.fir.isCopyCreatedInScope import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector @@ -73,12 +74,14 @@ private class LLFirExpectActualMatchingTargetResolver( } } -private fun FirMemberDeclaration.canHaveExpectCounterPart(): Boolean = when (this) { - is FirEnumEntry -> true - is FirProperty -> true - is FirConstructor -> true - is FirSimpleFunction -> true - is FirRegularClass -> true - is FirTypeAlias -> true +private fun FirMemberDeclaration.canHaveExpectCounterPart(): Boolean = when { + // We shouldn't try to calculate expect/actual mapping for fake declarations + this is FirCallableDeclaration && isCopyCreatedInScope -> false + this is FirEnumEntry -> true + this is FirProperty -> true + this is FirConstructor -> true + this is FirSimpleFunction -> true + this is FirRegularClass -> true + this is FirTypeAlias -> true else -> false } diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirFakeOverrideGenerator.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirFakeOverrideGenerator.kt index 4106516066c..3c5e67dea85 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirFakeOverrideGenerator.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirFakeOverrideGenerator.kt @@ -120,28 +120,24 @@ object FirFakeOverrideGenerator { newModality: Modality? = null, newVisibility: Visibility? = null, callableCopySubstitutionForTypeUpdater: CallableCopySubstitution? = null, - ): FirSimpleFunction { - checkStatusIsResolved(baseFunction) + ): FirSimpleFunction = buildSimpleFunction { + source = derivedClassLookupTag?.toSymbol(session)?.source ?: baseFunction.source + moduleData = session.nullableModuleData ?: baseFunction.moduleData + this.origin = origin + name = baseFunction.name + status = baseFunction.status.copy(newVisibility, newModality, isExpect = isExpect) + symbol = newSymbol + resolvePhase = origin.resolvePhaseForCopy - return buildSimpleFunction { - source = derivedClassLookupTag?.toSymbol(session)?.source ?: baseFunction.source - moduleData = session.nullableModuleData ?: baseFunction.moduleData - this.origin = origin - name = baseFunction.name - status = baseFunction.status.copy(newVisibility, newModality, isExpect = isExpect) - symbol = newSymbol - resolvePhase = baseFunction.resolvePhase - - dispatchReceiverType = newDispatchReceiverType - attributes = baseFunction.attributes.copy() - typeParameters += configureAnnotationsTypeParametersAndSignature( - session, baseFunction, newParameterTypes, newTypeParameters, - newReceiverType, newContextReceiverTypes, newReturnType, callableCopySubstitutionForTypeUpdater, newSymbol - ).filterIsInstance() - deprecationsProvider = baseFunction.deprecationsProvider - }.apply { - containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseFunction) } - } + dispatchReceiverType = newDispatchReceiverType + attributes = baseFunction.attributes.copy() + typeParameters += configureAnnotationsTypeParametersAndSignature( + session, baseFunction, newParameterTypes, newTypeParameters, + newReceiverType, newContextReceiverTypes, newReturnType, callableCopySubstitutionForTypeUpdater, newSymbol + ).filterIsInstance() + deprecationsProvider = baseFunction.deprecationsProvider + }.apply { + containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseFunction) } } fun createCopyForFirConstructor( @@ -157,46 +153,42 @@ object FirFakeOverrideGenerator { newTypeParameters: List?, isExpect: Boolean, callableCopySubstitutionForTypeUpdater: CallableCopySubstitution?, - ): FirConstructor { - checkStatusIsResolved(baseConstructor) - + ): FirConstructor = buildConstructor { // TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl // As second alternative, we can invent some light-weight kind of FirRegularClass - return buildConstructor { - annotations += baseConstructor.annotations - source = derivedClassLookupTag?.toSymbol(session)?.source ?: baseConstructor.source - moduleData = session.nullableModuleData ?: baseConstructor.moduleData - this.origin = origin - receiverParameter = baseConstructor.receiverParameter?.let { receiverParameter -> - buildReceiverParameterCopy(receiverParameter) { - typeRef = receiverParameter.typeRef.withReplacedConeType(null) - } + annotations += baseConstructor.annotations + source = derivedClassLookupTag?.toSymbol(session)?.source ?: baseConstructor.source + moduleData = session.nullableModuleData ?: baseConstructor.moduleData + this.origin = origin + receiverParameter = baseConstructor.receiverParameter?.let { receiverParameter -> + buildReceiverParameterCopy(receiverParameter) { + typeRef = receiverParameter.typeRef.withReplacedConeType(null) } - - status = baseConstructor.status.copy(isExpect = isExpect) - symbol = fakeOverrideSymbol - - typeParameters += configureAnnotationsTypeParametersAndSignature( - session, - baseConstructor, - newParameterTypes, - newTypeParameters, - newReceiverType = null, - newContextReceiverTypes, - newReturnType, - callableCopySubstitutionForTypeUpdater, - fakeOverrideSymbol - ) - - dispatchReceiverType = newDispatchReceiverType - - resolvePhase = baseConstructor.resolvePhase - attributes = baseConstructor.attributes.copy() - deprecationsProvider = baseConstructor.deprecationsProvider - }.apply { - originalForSubstitutionOverrideAttr = baseConstructor - containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseConstructor) } } + + status = baseConstructor.status.copy(isExpect = isExpect) + symbol = fakeOverrideSymbol + + typeParameters += configureAnnotationsTypeParametersAndSignature( + session, + baseConstructor, + newParameterTypes, + newTypeParameters, + newReceiverType = null, + newContextReceiverTypes, + newReturnType, + callableCopySubstitutionForTypeUpdater, + fakeOverrideSymbol + ) + + dispatchReceiverType = newDispatchReceiverType + + resolvePhase = origin.resolvePhaseForCopy + attributes = baseConstructor.attributes.copy() + deprecationsProvider = baseConstructor.deprecationsProvider + }.apply { + originalForSubstitutionOverrideAttr = baseConstructor + containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseConstructor) } } private fun FirFunctionBuilder.configureAnnotationsTypeParametersAndSignature( @@ -277,6 +269,7 @@ object FirFakeOverrideGenerator { callableCopySubstitutionForTypeUpdater: CallableCopySubstitution?, origin: FirDeclarationOrigin, ) { + checkStatusIsResolved(baseFunction) annotations += baseFunction.annotations @Suppress("NAME_SHADOWING") @@ -338,6 +331,8 @@ object FirFakeOverrideGenerator { coneTypeOrNull = returnTypeRef.coneTypeOrNull } } + + resolvePhase = origin.resolvePhaseForCopy }.apply { addOverrideAttributeIfNeeded(original) } @@ -397,55 +392,51 @@ object FirFakeOverrideGenerator { newModality: Modality? = null, newVisibility: Visibility? = null, callableCopySubstitutionForTypeUpdater: CallableCopySubstitution? = null, - ): FirProperty { - checkStatusIsResolved(baseProperty) + ): FirProperty = buildProperty { + source = derivedClassLookupTag?.toSymbol(session)?.source ?: baseProperty.source + moduleData = session.nullableModuleData ?: baseProperty.moduleData + this.origin = origin + name = baseProperty.name + isVar = baseProperty.isVar + this.symbol = newSymbol + isLocal = false + status = baseProperty.status.copy(newVisibility, newModality, isExpect = isExpect) - return buildProperty { - source = derivedClassLookupTag?.toSymbol(session)?.source ?: baseProperty.source - moduleData = session.nullableModuleData ?: baseProperty.moduleData - this.origin = origin - name = baseProperty.name - isVar = baseProperty.isVar - this.symbol = newSymbol - isLocal = false - status = baseProperty.status.copy(newVisibility, newModality, isExpect = isExpect) + resolvePhase = origin.resolvePhaseForCopy + dispatchReceiverType = newDispatchReceiverType + attributes = baseProperty.attributes.copy() + typeParameters += configureAnnotationsTypeParametersAndSignature( + session, + baseProperty, + newTypeParameters, + newReceiverType, + newContextReceiverTypes, + newReturnType, + callableCopySubstitutionForTypeUpdater + ) + deprecationsProvider = baseProperty.deprecationsProvider - resolvePhase = baseProperty.resolvePhase - dispatchReceiverType = newDispatchReceiverType - attributes = baseProperty.attributes.copy() - typeParameters += configureAnnotationsTypeParametersAndSignature( - session, - baseProperty, - newTypeParameters, - newReceiverType, - newContextReceiverTypes, - newReturnType, - callableCopySubstitutionForTypeUpdater - ) - deprecationsProvider = baseProperty.deprecationsProvider + getter = baseProperty.getter?.buildCopyIfNeeded( + moduleData = session.nullableModuleData ?: baseProperty.moduleData, + origin = origin, + propertyReturnTypeRef = this@buildProperty.returnTypeRef, + propertySymbol = newSymbol, + dispatchReceiverType = dispatchReceiverType, + derivedClassLookupTag = derivedClassLookupTag, + baseProperty = baseProperty, + ) - getter = baseProperty.getter?.buildCopyIfNeeded( - moduleData = session.nullableModuleData ?: baseProperty.moduleData, - origin = origin, - propertyReturnTypeRef = this@buildProperty.returnTypeRef, - propertySymbol = newSymbol, - dispatchReceiverType = dispatchReceiverType, - derivedClassLookupTag = derivedClassLookupTag, - baseProperty = baseProperty, - ) - - setter = baseProperty.setter?.buildCopyIfNeeded( - moduleData = session.nullableModuleData ?: baseProperty.moduleData, - origin = origin, - propertyReturnTypeRef = this@buildProperty.returnTypeRef, - propertySymbol = newSymbol, - dispatchReceiverType = dispatchReceiverType, - derivedClassLookupTag = derivedClassLookupTag, - baseProperty = baseProperty, - ) - }.apply { - containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseProperty) } - } + setter = baseProperty.setter?.buildCopyIfNeeded( + moduleData = session.nullableModuleData ?: baseProperty.moduleData, + origin = origin, + propertyReturnTypeRef = this@buildProperty.returnTypeRef, + propertySymbol = newSymbol, + dispatchReceiverType = dispatchReceiverType, + derivedClassLookupTag = derivedClassLookupTag, + baseProperty = baseProperty, + ) + }.apply { + containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseProperty) } } private fun FirPropertyAccessor.buildCopyIfNeeded( @@ -487,7 +478,7 @@ object FirFakeOverrideGenerator { propertySymbol = propertySymbol, modality = modality ?: Modality.FINAL, effectiveVisibility = effectiveVisibility, - resolvePhase = resolvePhase, + resolvePhase = origin.resolvePhaseForCopy, ).apply { replaceAnnotations(this@buildCopy.annotations) } @@ -500,7 +491,7 @@ object FirFakeOverrideGenerator { propertySymbol = propertySymbol, modality = modality ?: Modality.FINAL, effectiveVisibility = effectiveVisibility, - resolvePhase = resolvePhase, + resolvePhase = origin.resolvePhaseForCopy, ).apply { replaceAnnotations(this@buildCopy.annotations) } @@ -511,6 +502,7 @@ object FirFakeOverrideGenerator { this.propertySymbol = propertySymbol this.dispatchReceiverType = dispatchReceiverType this.body = null + resolvePhase = origin.resolvePhaseForCopy }.also { if (it.isSetter) { val originalParameter = it.valueParameters.first() @@ -547,27 +539,25 @@ object FirFakeOverrideGenerator { newModality: Modality? = null, newVisibility: Visibility? = null, callableCopySubstitutionForTypeUpdater: CallableCopySubstitution? = null, - ): FirField { - return buildField { - source = baseField.source - moduleData = session.nullableModuleData ?: baseField.moduleData - this.origin = origin - name = baseField.name - isVar = baseField.isVar - this.symbol = newSymbol - status = baseField.status.copy(newVisibility, newModality, isExpect = isExpect) + ): FirField = buildField { + source = baseField.source + moduleData = session.nullableModuleData ?: baseField.moduleData + this.origin = origin + name = baseField.name + isVar = baseField.isVar + this.symbol = newSymbol + status = baseField.status.copy(newVisibility, newModality, isExpect = isExpect) - resolvePhase = baseField.resolvePhase - dispatchReceiverType = newDispatchReceiverType - attributes = baseField.attributes.copy() - configureAnnotationsAndSignature( - baseField, newReceiverType, newContextReceiverTypes, newReturnType, - callableCopySubstitutionForTypeUpdater, updateReceiver = false - ) - deprecationsProvider = baseField.deprecationsProvider - }.apply { - containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseField) } - } + resolvePhase = origin.resolvePhaseForCopy + dispatchReceiverType = newDispatchReceiverType + attributes = baseField.attributes.copy() + configureAnnotationsAndSignature( + baseField, newReceiverType, newContextReceiverTypes, newReturnType, + callableCopySubstitutionForTypeUpdater, updateReceiver = false + ) + deprecationsProvider = baseField.deprecationsProvider + }.apply { + containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseField) } } private fun FirPropertyBuilder.configureAnnotationsTypeParametersAndSignature( @@ -652,6 +642,7 @@ object FirFakeOverrideGenerator { callableCopySubstitutionForTypeUpdater: CallableCopySubstitution?, updateReceiver: Boolean = true, ) { + checkStatusIsResolved(baseVariable) annotations += baseVariable.annotations @Suppress("NAME_SHADOWING") @@ -690,29 +681,25 @@ object FirFakeOverrideGenerator { derivedClassLookupTag: ConeClassLikeLookupTag, newReturnType: ConeKotlinType?, origin: FirDeclarationOrigin.SubstitutionOverride, - ): FirFieldSymbol { + ): FirFieldSymbol = buildField { val symbol = FirFieldSymbol(CallableId(derivedClassLookupTag.classId, baseField.name)) - buildField { - moduleData = session.nullableModuleData ?: baseField.moduleData - this.symbol = symbol - this.origin = origin - returnTypeRef = baseField.returnTypeRef.withReplacedConeType(newReturnType) + moduleData = session.nullableModuleData ?: baseField.moduleData + this.symbol = symbol + this.origin = origin + returnTypeRef = baseField.returnTypeRef.withReplacedConeType(newReturnType) - source = baseField.source - resolvePhase = baseField.resolvePhase - name = baseField.name - isVar = baseField.isVar - status = baseField.status - resolvePhase = baseField.resolvePhase - annotations += baseField.annotations - attributes = baseField.attributes.copy() - dispatchReceiverType = baseField.dispatchReceiverType - }.apply { - originalForSubstitutionOverrideAttr = baseField - containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseField) } - } - return symbol - } + source = baseField.source + name = baseField.name + isVar = baseField.isVar + status = baseField.status + resolvePhase = origin.resolvePhaseForCopy + annotations += baseField.annotations + attributes = baseField.attributes.copy() + dispatchReceiverType = baseField.dispatchReceiverType + }.apply { + originalForSubstitutionOverrideAttr = baseField + containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseField) } + }.symbol // Returns a list of type parameters, and a substitutor that should be used for all other types fun createNewTypeParametersAndSubstitutor( @@ -730,7 +717,7 @@ object FirFakeOverrideGenerator { source = typeParameter.source moduleData = typeParameter.moduleData this.origin = origin - resolvePhase = FirResolvePhase.DECLARATIONS + resolvePhase = origin.resolvePhaseForCopy name = typeParameter.name symbol = FirTypeParameterSymbol() variance = typeParameter.variance @@ -794,4 +781,24 @@ object FirFakeOverrideGenerator { withEntry("declarationStatus", member.status) { it.toString() } } } + + /** + * In Low Level FIR we cannot be sure that all copied elements are already resolved, + * so we play safe with [FirResolvePhase.STATUS] phase in such cases. + * Example: + * ```kotlin + * class MyClass : BaseClass<@Anno("super $constant") Int>() + * + * abstract class BaseClass { + * var property: SCHEME + * } + * ``` + * here we can have `BaseClass.property` already in [FirResolvePhase.BODY_RESOLVE] phase, + * but `MyClass` in [FirResolvePhase.STATUS]. + * So [FirResolvePhase.BODY_RESOLVE] on the fake override will lead to the problem because + * effectively we will have unresolved `@Anno("super $constant")` annotation inside "fully resolve" + * function + */ + private val FirDeclarationOrigin.resolvePhaseForCopy: FirResolvePhase + get() = if (isLazyResolvable) FirResolvePhase.STATUS else FirResolvePhase.BODY_RESOLVE } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationOrigin.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationOrigin.kt index 26075b7cf86..6ce4c311772 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationOrigin.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationOrigin.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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. */ @@ -63,3 +63,21 @@ sealed class FirDeclarationOrigin( val GeneratedDeclarationKey.origin: FirDeclarationOrigin get() = FirDeclarationOrigin.Plugin(this) + +/** + * @return **true** if a declaration with [this] origin can be in not fully resolved state + */ +val FirDeclarationOrigin.isLazyResolvable: Boolean + get() = when (this) { + is FirDeclarationOrigin.Source, + is FirDeclarationOrigin.ImportedFromObjectOrStatic, + is FirDeclarationOrigin.Delegated, + is FirDeclarationOrigin.Synthetic, + is FirDeclarationOrigin.SubstitutionOverride, + is FirDeclarationOrigin.SamConstructor, + is FirDeclarationOrigin.WrappedIntegerOperator, + is FirDeclarationOrigin.IntersectionOverride, + is FirDeclarationOrigin.ScriptCustomization, + -> true + else -> false + } \ No newline at end of file