From c66fbf5c0edc8819af822b6e96c4305298af3358 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Thu, 1 Dec 2022 16:45:36 +0100 Subject: [PATCH] [LL FIR] fix lazy resolution of member-property statuses for local classes Previously, statuses of superclass which are not local was not ignored Sometimes it worked in the IDE by calling lazyResolveToPhase which is a violation of the lazy resolution contract ^KT-54890 --- ...LLFirDesignatedStatusResolveTransformer.kt | 2 +- ...nosisCompilerFirTestdataTestGenerated.java | 6 ++ ...TouchedTilContractsPhaseTestGenerated.java | 5 ++ .../localClasses/overrideInLocal.fir.txt | 23 ++++++ .../resolve/localClasses/overrideInLocal.kt | 11 +++ .../runners/FirDiagnosticTestGenerated.java | 6 ++ ...DiagnosticsWithLightTreeTestGenerated.java | 6 ++ .../FirStatusResolveTransformer.kt | 71 ++++++------------- 8 files changed, 79 insertions(+), 51 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/localClasses/overrideInLocal.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/localClasses/overrideInLocal.kt diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirDesignatedStatusResolveTransformer.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirDesignatedStatusResolveTransformer.kt index 27d7aaf92a2..cb648259c05 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirDesignatedStatusResolveTransformer.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirDesignatedStatusResolveTransformer.kt @@ -26,7 +26,7 @@ internal class LLFirDesignatedStatusResolveTransformer( private val scopeSession: ScopeSession, ) : LLFirLazyTransformer { private inner class FirDesignatedStatusResolveTransformerForIDE : - FirStatusResolveTransformer(session, scopeSession, StatusComputationSession.Regular()) { + FirStatusResolveTransformer(session, scopeSession, StatusComputationSession()) { val designationTransformer = LLFirDeclarationTransformer(designation) diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java index 266a34adcd8..a34edcc6117 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java @@ -3163,6 +3163,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/implicitInLocalClasses.kt"); } + @Test + @TestMetadata("overrideInLocal.kt") + public void testOverrideInLocal() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/overrideInLocal.kt"); + } + @Test @TestMetadata("typesFromSuperClasses.kt") public void testTypesFromSuperClasses() throws Exception { diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java index 3c9c1da0b11..b86989e7b5f 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java @@ -2783,6 +2783,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/implicitInLocalClasses.kt"); } + @TestMetadata("overrideInLocal.kt") + public void testOverrideInLocal() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/overrideInLocal.kt"); + } + @TestMetadata("typesFromSuperClasses.kt") public void testTypesFromSuperClasses() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/typesFromSuperClasses.kt"); diff --git a/compiler/fir/analysis-tests/testData/resolve/localClasses/overrideInLocal.fir.txt b/compiler/fir/analysis-tests/testData/resolve/localClasses/overrideInLocal.fir.txt new file mode 100644 index 00000000000..9531124d5c9 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/localClasses/overrideInLocal.fir.txt @@ -0,0 +1,23 @@ +FILE: a.kt + public final fun main(): R|kotlin/Unit| { + local final class Local : R|B| { + public constructor(): R|Local| { + super() + } + + protected final override val message: R|kotlin/String| = String(expression expected) + protected get(): R|kotlin/String| + + } + + } +FILE: b.kt + public abstract class B : R|kotlin/Any| { + public constructor(): R|B| { + super() + } + + protected abstract val message: R|kotlin/String| + protected get(): R|kotlin/String| + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/localClasses/overrideInLocal.kt b/compiler/fir/analysis-tests/testData/resolve/localClasses/overrideInLocal.kt new file mode 100644 index 00000000000..a9f5a7268d5 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/localClasses/overrideInLocal.kt @@ -0,0 +1,11 @@ +// FILE: a.kt +fun main() { + class Local : B() { + override val message = "expression expected" + } +} + +// FILE: b.kt +abstract class B { + protected abstract val message: String +} \ No newline at end of file diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java index 2dce587400e..58afb847c01 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java @@ -3163,6 +3163,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/implicitInLocalClasses.kt"); } + @Test + @TestMetadata("overrideInLocal.kt") + public void testOverrideInLocal() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/overrideInLocal.kt"); + } + @Test @TestMetadata("typesFromSuperClasses.kt") public void testTypesFromSuperClasses() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java index d100318a864..7cf72f9628e 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java @@ -3163,6 +3163,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/implicitInLocalClasses.kt"); } + @Test + @TestMetadata("overrideInLocal.kt") + public void testOverrideInLocal() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/overrideInLocal.kt"); + } + @Test @TestMetadata("typesFromSuperClasses.kt") public void testTypesFromSuperClasses() throws Exception { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt index 70843af454f..bccc29d4952 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt @@ -37,7 +37,7 @@ class FirStatusResolveProcessor( scopeSession: ScopeSession ) : FirTransformerBasedResolveProcessor(session, scopeSession) { override val transformer = run { - val statusComputationSession = StatusComputationSession.Regular() + val statusComputationSession = StatusComputationSession() FirStatusResolveTransformer( session, scopeSession, @@ -52,7 +52,7 @@ fun F.runStatusResolveForLocalClass( scopesForLocalClass: List, localClassesNavigationInfo: LocalClassesNavigationInfo ): F { - val statusComputationSession = StatusComputationSession.ForLocalClassResolution(localClassesNavigationInfo.parentForClass.keys) + val statusComputationSession = StatusComputationSession() val transformer = FirStatusResolveTransformer( session, scopeSession, @@ -174,12 +174,26 @@ open class FirDesignatedStatusResolveTransformer( } } -sealed class StatusComputationSession { - abstract operator fun get(klass: FirClass): StatusComputationStatus +class StatusComputationSession { + private val statusMap = mutableMapOf() + .withDefault { StatusComputationStatus.NotComputed } - abstract fun startComputing(klass: FirClass): StatusComputationStatus - abstract fun endComputing(klass: FirClass) - abstract fun computeOnlyClassStatus(klass: FirClass) + operator fun get(klass: FirClass): StatusComputationStatus = statusMap.getValue(klass) + + fun startComputing(klass: FirClass): StatusComputationStatus { + return statusMap.getOrPut(klass) { StatusComputationStatus.Computing } + } + + fun endComputing(klass: FirClass) { + statusMap[klass] = StatusComputationStatus.Computed + } + + fun computeOnlyClassStatus(klass: FirClass) { + val existedStatus = statusMap.getValue(klass) + if (existedStatus < StatusComputationStatus.ComputedOnlyClassStatus) { + statusMap[klass] = StatusComputationStatus.ComputedOnlyClassStatus + } + } enum class StatusComputationStatus(val requiresComputation: Boolean) { NotComputed(true), @@ -187,49 +201,6 @@ sealed class StatusComputationSession { ComputedOnlyClassStatus(true), Computed(false) } - - class Regular : StatusComputationSession() { - private val statusMap = mutableMapOf() - .withDefault { StatusComputationStatus.NotComputed } - - override fun get(klass: FirClass): StatusComputationStatus = statusMap.getValue(klass) - - override fun startComputing(klass: FirClass): StatusComputationStatus { - return statusMap.getOrPut(klass) { StatusComputationStatus.Computing } - } - - override fun endComputing(klass: FirClass) { - statusMap[klass] = StatusComputationStatus.Computed - } - - override fun computeOnlyClassStatus(klass: FirClass) { - val existedStatus = statusMap.getValue(klass) - if (existedStatus < StatusComputationStatus.ComputedOnlyClassStatus) { - statusMap[klass] = StatusComputationStatus.ComputedOnlyClassStatus - } - } - } - - class ForLocalClassResolution(private val localClasses: Set) : StatusComputationSession() { - private val delegate = Regular() - - override fun get(klass: FirClass): StatusComputationStatus { - if (klass !in localClasses) return StatusComputationStatus.Computed - return delegate[klass] - } - - override fun startComputing(klass: FirClass): StatusComputationStatus { - return delegate.startComputing(klass) - } - - override fun endComputing(klass: FirClass) { - delegate.endComputing(klass) - } - - override fun computeOnlyClassStatus(klass: FirClass) { - delegate.computeOnlyClassStatus(klass) - } - } } abstract class AbstractFirStatusResolveTransformer(