[LL FIR] fix lazy resolution of member property statuses for anonymous objects
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:
Vendored
+1
-1
@@ -156,7 +156,7 @@ FILE: anonympuseObjectInInvalidPosition.kt
|
||||
}
|
||||
|
||||
private [BODY_RESOLVE] get(): <ERROR TYPE REF: Wrong number of type arguments>
|
||||
public abstract [SUPER_TYPES] interface A<[SUPER_TYPES] T> : R|kotlin/Any| {
|
||||
public abstract [TYPES] interface A<[TYPES] T> : R|kotlin/Any| {
|
||||
public abstract [STATUS] fun x(): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
|
||||
+6
@@ -3145,6 +3145,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/localClasses"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("anonObject.kt")
|
||||
public void testAnonObject() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/anonObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("anonymousInAnonymous.kt")
|
||||
public void testAnonymousInAnonymous() throws Exception {
|
||||
|
||||
+5
@@ -2768,6 +2768,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/localClasses"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("anonObject.kt")
|
||||
public void testAnonObject() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/anonObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("anonymousInAnonymous.kt")
|
||||
public void testAnonymousInAnonymous() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/anonymousInAnonymous.kt");
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
FILE: a.kt
|
||||
public final object A : R|kotlin/Any| {
|
||||
private constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val O: R|B| = object : R|B| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|B|>()
|
||||
}
|
||||
|
||||
protected final override val message: R|kotlin/String| = String(expression expected)
|
||||
protected get(): R|kotlin/String|
|
||||
|
||||
}
|
||||
|
||||
public get(): R|B|
|
||||
|
||||
}
|
||||
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
|
||||
object A {
|
||||
val O = object : B() {
|
||||
override val message = "expression expected"
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: b.kt
|
||||
abstract class B {
|
||||
protected abstract val message: String
|
||||
}
|
||||
+6
@@ -3145,6 +3145,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/localClasses"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("anonObject.kt")
|
||||
public void testAnonObject() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/anonObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("anonymousInAnonymous.kt")
|
||||
public void testAnonymousInAnonymous() throws Exception {
|
||||
|
||||
+6
@@ -3145,6 +3145,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/localClasses"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("anonObject.kt")
|
||||
public void testAnonObject() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/anonObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("anonymousInAnonymous.kt")
|
||||
public void testAnonymousInAnonymous() throws Exception {
|
||||
|
||||
+34
-41
@@ -5,19 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.transformers
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInline
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.LocalClassesNavigationInfo
|
||||
import org.jetbrains.kotlin.fir.scopes.FirCompositeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
@@ -102,23 +97,23 @@ open class FirStatusResolveTransformer(
|
||||
return true
|
||||
}
|
||||
|
||||
override fun transformRegularClass(
|
||||
regularClass: FirRegularClass,
|
||||
override fun transformClassContent(
|
||||
firClass: FirClass,
|
||||
data: FirResolvedDeclarationStatus?
|
||||
): FirStatement = whileAnalysing(regularClass) {
|
||||
val computationStatus = statusComputationSession.startComputing(regularClass)
|
||||
forceResolveStatusesOfSupertypes(regularClass)
|
||||
): FirStatement {
|
||||
val computationStatus = statusComputationSession.startComputing(firClass)
|
||||
forceResolveStatusesOfSupertypes(firClass)
|
||||
/*
|
||||
* Status of class may be already calculated if that class was in supertypes of one of previous classes
|
||||
*/
|
||||
if (computationStatus != StatusComputationSession.StatusComputationStatus.Computed) {
|
||||
regularClass.transformStatus(this, statusResolver.resolveStatus(regularClass, containingClass, isLocal = false))
|
||||
if (regularClass.isInline) {
|
||||
regularClass.valueClassRepresentation = computeValueClassRepresentation(regularClass, session)
|
||||
firClass.transformStatus(this, statusResolver.resolveStatus(firClass, containingClass, isLocal = false))
|
||||
if (firClass is FirRegularClass && firClass.isInline) {
|
||||
firClass.valueClassRepresentation = computeValueClassRepresentation(firClass, session)
|
||||
}
|
||||
}
|
||||
return transformClass(regularClass, data).also {
|
||||
statusComputationSession.endComputing(regularClass)
|
||||
return transformClass(firClass, data).also {
|
||||
statusComputationSession.endComputing(firClass)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,31 +140,31 @@ open class FirDesignatedStatusResolveTransformer(
|
||||
return !designation.classLocated
|
||||
}
|
||||
|
||||
override fun transformRegularClass(
|
||||
regularClass: FirRegularClass,
|
||||
override fun transformClassContent(
|
||||
firClass: FirClass,
|
||||
data: FirResolvedDeclarationStatus?
|
||||
): FirStatement = whileAnalysing(regularClass) {
|
||||
if (designation.shouldSkipClass(regularClass)) return regularClass
|
||||
regularClass.symbol.lazyResolveToPhase(FirResolvePhase.TYPES)
|
||||
): FirStatement = whileAnalysing(firClass) {
|
||||
if (designation.shouldSkipClass(firClass)) return firClass
|
||||
firClass.symbol.lazyResolveToPhase(FirResolvePhase.TYPES)
|
||||
val classLocated = designation.classLocated
|
||||
/*
|
||||
* In designated status resolve we should resolve status only of target class and it's members
|
||||
*/
|
||||
if (classLocated) {
|
||||
assert(regularClass == designation.targetClass)
|
||||
val computationStatus = statusComputationSession.startComputing(regularClass)
|
||||
forceResolveStatusesOfSupertypes(regularClass)
|
||||
assert(firClass == designation.targetClass)
|
||||
val computationStatus = statusComputationSession.startComputing(firClass)
|
||||
forceResolveStatusesOfSupertypes(firClass)
|
||||
if (computationStatus != StatusComputationSession.StatusComputationStatus.Computed) {
|
||||
regularClass.transformStatus(this, statusResolver.resolveStatus(regularClass, containingClass, isLocal = false))
|
||||
firClass.transformStatus(this, statusResolver.resolveStatus(firClass, containingClass, isLocal = false))
|
||||
}
|
||||
} else {
|
||||
if (regularClass.status !is FirResolvedDeclarationStatus) {
|
||||
regularClass.transformStatus(this, statusResolver.resolveStatus(regularClass, containingClass, isLocal = false))
|
||||
statusComputationSession.computeOnlyClassStatus(regularClass)
|
||||
if (firClass.status !is FirResolvedDeclarationStatus) {
|
||||
firClass.transformStatus(this, statusResolver.resolveStatus(firClass, containingClass, isLocal = false))
|
||||
statusComputationSession.computeOnlyClassStatus(firClass)
|
||||
}
|
||||
}
|
||||
return transformClass(regularClass, data).also {
|
||||
if (classLocated) statusComputationSession.endComputing(regularClass)
|
||||
return transformClass(firClass, data).also {
|
||||
if (classLocated) statusComputationSession.endComputing(firClass)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -268,25 +263,23 @@ abstract class AbstractFirStatusResolveTransformer(
|
||||
return transformDeclaration(typeAlias, data) as FirTypeAlias
|
||||
}
|
||||
|
||||
abstract override fun transformRegularClass(
|
||||
override fun transformRegularClass(
|
||||
regularClass: FirRegularClass,
|
||||
data: FirResolvedDeclarationStatus?
|
||||
): FirStatement = whileAnalysing(regularClass) {
|
||||
transformClassContent(regularClass, data)
|
||||
}
|
||||
|
||||
abstract fun transformClassContent(
|
||||
firClass: FirClass,
|
||||
data: FirResolvedDeclarationStatus?
|
||||
): FirStatement
|
||||
|
||||
override fun transformAnonymousObject(
|
||||
anonymousObject: FirAnonymousObject,
|
||||
data: FirResolvedDeclarationStatus?
|
||||
): FirStatement = whileAnalysing(anonymousObject) {
|
||||
anonymousObject.transformStatus(
|
||||
this,
|
||||
FirResolvedDeclarationStatusImpl(
|
||||
anonymousObject.status.visibility,
|
||||
anonymousObject.status.modality ?: Modality.FINAL,
|
||||
EffectiveVisibility.Local
|
||||
)
|
||||
)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return transformClass(anonymousObject, data)
|
||||
transformClassContent(anonymousObject, data)
|
||||
}
|
||||
|
||||
open fun transformDeclarationContent(
|
||||
@@ -329,7 +322,7 @@ abstract class AbstractFirStatusResolveTransformer(
|
||||
} as FirStatement
|
||||
}
|
||||
|
||||
protected fun forceResolveStatusesOfSupertypes(regularClass: FirRegularClass) {
|
||||
protected fun forceResolveStatusesOfSupertypes(regularClass: FirClass) {
|
||||
for (superTypeRef in regularClass.superTypeRefs) {
|
||||
forceResolveStatusOfCorrespondingClass(superTypeRef)
|
||||
}
|
||||
|
||||
+6
-3
@@ -152,12 +152,15 @@ class FirStatusResolver(
|
||||
}
|
||||
|
||||
fun resolveStatus(
|
||||
regularClass: FirRegularClass,
|
||||
firClass: FirClass,
|
||||
containingClass: FirClass?,
|
||||
isLocal: Boolean
|
||||
): FirResolvedDeclarationStatus {
|
||||
val status = regularClass.applyExtensionTransformers { transformStatus(it, regularClass, containingClass, isLocal) }
|
||||
return resolveStatus(regularClass, status, containingClass, null, isLocal, emptyList())
|
||||
val status = when (firClass) {
|
||||
is FirRegularClass -> firClass.applyExtensionTransformers { transformStatus(it, firClass, containingClass, isLocal) }
|
||||
else -> firClass.status
|
||||
}
|
||||
return resolveStatus(firClass, status, containingClass, null, isLocal, emptyList())
|
||||
}
|
||||
|
||||
fun resolveStatus(
|
||||
|
||||
Reference in New Issue
Block a user