diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt index e83950257e3..f7c98dd9290 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt @@ -16,11 +16,8 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.LLFirDecla import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirModuleData import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableResolveSession -import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkDelegatedConstructorIsResolved import org.jetbrains.kotlin.analysis.low.level.api.fir.util.* -import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry -import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment -import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment +import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkDelegatedConstructorIsResolved import org.jetbrains.kotlin.fir.FirElementWithResolveState import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer import org.jetbrains.kotlin.fir.FirSession @@ -40,19 +37,22 @@ import org.jetbrains.kotlin.fir.references.builder.buildExplicitThisReference import org.jetbrains.kotlin.fir.resolve.FirCodeFragmentContext import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.SessionHolderImpl -import org.jetbrains.kotlin.fir.resolve.dfa.FirControlFlowGraphReferenceImpl import org.jetbrains.kotlin.fir.resolve.codeFragmentContext +import org.jetbrains.kotlin.fir.resolve.dfa.FirControlFlowGraphReferenceImpl import org.jetbrains.kotlin.fir.resolve.dfa.RealVariable +import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isUsedInControlFlowGraphBuilderForClass +import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isUsedInControlFlowGraphBuilderForFile import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector import org.jetbrains.kotlin.fir.resolve.transformers.contracts.FirContractsDslNames import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase -import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isUsedInControlFlowGraphBuilderForClass -import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isUsedInControlFlowGraphBuilderForFile import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.isResolved +import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry import org.jetbrains.kotlin.psi.KtCodeFragment import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment +import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment import org.jetbrains.kotlin.utils.exceptions.requireWithAttachment import org.jetbrains.kotlin.utils.exceptions.withPsiEntry import org.jetbrains.kotlin.utils.findIsInstanceAnd @@ -107,6 +107,11 @@ private class LLFirBodyTargetResolver( override val buildCfgForFiles: Boolean get() = false } + /** + * No one should depend on body resolution of another declaration + */ + override val skipDependencyTargetResolutionStep: Boolean get() = true + override fun doResolveWithoutLock(target: FirElementWithResolveState): Boolean { when (target) { is FirRegularClass -> { @@ -123,7 +128,7 @@ private class LLFirBodyTargetResolver( is FirFile -> { if (target.resolvePhase >= resolverPhase) return true - resolveFileAnnotationContainerIfNeeded(target) + target.annotationsContainer?.lazyResolveToPhase(resolverPhase) // resolve file CFG graph here, to do this we need to have property blocks resoled resolveMembersForControlFlowGraph(target) @@ -143,7 +148,7 @@ private class LLFirBodyTargetResolver( } } - return super.doResolveWithoutLock(target) + return false } private fun calculateControlFlowGraph(target: FirRegularClass) { diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirCompilerAnnotationsLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirCompilerAnnotationsLazyResolver.kt index 1503757ac4d..ba2a418ec42 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirCompilerAnnotationsLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirCompilerAnnotationsLazyResolver.kt @@ -13,14 +13,16 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockPro import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkDeprecationProviderIsResolved +import org.jetbrains.kotlin.analysis.low.level.api.fir.util.forEachDependentDeclaration +import org.jetbrains.kotlin.analysis.low.level.api.fir.util.isScriptDependentDeclaration import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance import org.jetbrains.kotlin.fir.FirAnnotationContainer import org.jetbrains.kotlin.fir.FirElementWithResolveState import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.util.PrivateForInline import org.jetbrains.kotlin.fir.caches.firCachesFactory import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.annotationPlatformSupport import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCallCopy @@ -31,9 +33,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirCompilerRequiredA import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.types.FirUserTypeRef -import org.jetbrains.kotlin.analysis.low.level.api.fir.util.forEachDependentDeclaration -import org.jetbrains.kotlin.analysis.low.level.api.fir.util.isScriptDependentDeclaration -import org.jetbrains.kotlin.fir.declarations.annotationPlatformSupport +import org.jetbrains.kotlin.util.PrivateForInline internal object LLFirCompilerAnnotationsLazyResolver : LLFirLazyResolver(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS) { override fun resolve( @@ -103,12 +103,8 @@ private class LLFirCompilerRequiredAnnotationsTargetResolver( } override fun doResolveWithoutLock(target: FirElementWithResolveState): Boolean { - if (target is FirFile) { - resolveFileAnnotationContainerIfNeeded(target) - return false - } - when (target) { + is FirFile -> return false is FirRegularClass, is FirScript, is FirCodeFragment -> {} else -> { if (!target.isRegularDeclarationWithAnnotation) { diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirStatusLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirStatusLazyResolver.kt index aae33a2677d..65fbe1b33a3 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirStatusLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirStatusLazyResolver.kt @@ -148,7 +148,7 @@ private class LLFirStatusTargetResolver( true } - else -> super.doResolveWithoutLock(target) + else -> false } private inline fun performResolveWithOverriddenCallables( diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirSupertypeLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirSupertypeLazyResolver.kt index ad24d314846..4c6bdafa00a 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirSupertypeLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirSupertypeLazyResolver.kt @@ -120,7 +120,6 @@ private class LLFirSuperTypeTargetResolver( superTypeUpdater = { target.replaceExpandedTypeRef(it.single()) }, ) else -> { - resolveFileAnnotationContainerIfNeeded(target) performCustomResolveUnderLock(target) { // just update the phase } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTargetResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTargetResolver.kt index 1f3473381ed..8037f25788e 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTargetResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTargetResolver.kt @@ -27,7 +27,7 @@ internal abstract class LLFirTargetResolver( /** * Must be executed without a lock */ - protected fun resolveFileAnnotationContainerIfNeeded(elementWithResolveState: FirElementWithResolveState) { + private fun resolveFileAnnotationContainerIfNeeded(elementWithResolveState: FirElementWithResolveState) { if (elementWithResolveState !is FirFile) return val annotationContainer = elementWithResolveState.annotationsContainer ?: return withFile(elementWithResolveState) { @@ -35,6 +35,23 @@ internal abstract class LLFirTargetResolver( } } + /** + * @see resolveDependencyTarget + */ + open val skipDependencyTargetResolutionStep: Boolean get() = false + + /** + * Requests the resolution for dependency targets to avoid race in the case of FIR instance sharing. + * Will be executed before resolution without a lock. + * + * @see skipDependencyTargetResolutionStep + */ + private fun resolveDependencyTarget(target: FirElementWithResolveState) { + if (skipDependencyTargetResolutionStep) return + + resolveFileAnnotationContainerIfNeeded(target) + } + override fun withFile(firFile: FirFile, action: () -> Unit) { action() } @@ -57,10 +74,7 @@ internal abstract class LLFirTargetResolver( protected open fun checkResolveConsistency() {} - protected open fun doResolveWithoutLock(target: FirElementWithResolveState): Boolean { - resolveFileAnnotationContainerIfNeeded(target) - return false - } + protected open fun doResolveWithoutLock(target: FirElementWithResolveState): Boolean = false protected abstract fun doLazyResolveUnderLock(target: FirElementWithResolveState) @@ -74,6 +88,8 @@ internal abstract class LLFirTargetResolver( } protected fun performResolve(target: FirElementWithResolveState) { + resolveDependencyTarget(target) + if (doResolveWithoutLock(target)) return performCustomResolveUnderLock(target) { doLazyResolveUnderLock(target) diff --git a/analysis/low-level-api-fir/testData/lazyResolve/annotations.txt b/analysis/low-level-api-fir/testData/lazyResolve/annotations.txt index 4b9547efba4..244a5d8fddf 100644 --- a/analysis/low-level-api-fir/testData/lazyResolve/annotations.txt +++ b/analysis/low-level-api-fir/testData/lazyResolve/annotations.txt @@ -70,7 +70,7 @@ FILE: [ResolvedTo(IMPORTS)] annotations.kt BODY_RESOLVE: FILE: [ResolvedTo(IMPORTS)] annotations.kt @FILE:R|kotlin/Suppress|[Types](names = vararg(String(1))) - [ResolvedTo(BODY_RESOLVE)] annotations container + [ResolvedTo(ANNOTATION_ARGUMENTS)] annotations container @R|kotlin/Suppress|[Types](names = vararg(String(2))) public final [ResolvedTo(BODY_RESOLVE)] fun resolveMe(): R|kotlin/Unit| { } diff --git a/analysis/low-level-api-fir/testData/lazyResolve/annotationsScript.txt b/analysis/low-level-api-fir/testData/lazyResolve/annotationsScript.txt index eda78025fb6..be83e37952e 100644 --- a/analysis/low-level-api-fir/testData/lazyResolve/annotationsScript.txt +++ b/analysis/low-level-api-fir/testData/lazyResolve/annotationsScript.txt @@ -125,7 +125,7 @@ FILE: [ResolvedTo(IMPORTS)] annotationsScript.kts BODY_RESOLVE: FILE: [ResolvedTo(IMPORTS)] annotationsScript.kts @FILE:R|kotlin/Suppress|[Types](names = vararg(String(1))) - [ResolvedTo(BODY_RESOLVE)] annotations container + [ResolvedTo(ANNOTATION_ARGUMENTS)] annotations container context(