[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
This commit is contained in:
Ilya Kirillov
2022-12-01 16:45:36 +01:00
parent 1550a37b17
commit c66fbf5c0e
8 changed files with 79 additions and 51 deletions
@@ -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)
@@ -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 {
@@ -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");
@@ -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<R|B|>()
}
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<R|kotlin/Any|>()
}
protected abstract val message: R|kotlin/String|
protected get(): R|kotlin/String|
}
@@ -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
}
@@ -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 {
@@ -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 {
@@ -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 : FirClassLikeDeclaration> F.runStatusResolveForLocalClass(
scopesForLocalClass: List<FirScope>,
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<FirClass, StatusComputationStatus>()
.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<FirClass, StatusComputationStatus>()
.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<FirClassLikeDeclaration>) : 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(