[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>
|
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|
|
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);
|
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
|
@Test
|
||||||
@TestMetadata("anonymousInAnonymous.kt")
|
@TestMetadata("anonymousInAnonymous.kt")
|
||||||
public void testAnonymousInAnonymous() throws Exception {
|
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);
|
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")
|
@TestMetadata("anonymousInAnonymous.kt")
|
||||||
public void testAnonymousInAnonymous() throws Exception {
|
public void testAnonymousInAnonymous() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/anonymousInAnonymous.kt");
|
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);
|
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
|
@Test
|
||||||
@TestMetadata("anonymousInAnonymous.kt")
|
@TestMetadata("anonymousInAnonymous.kt")
|
||||||
public void testAnonymousInAnonymous() throws Exception {
|
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);
|
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
|
@Test
|
||||||
@TestMetadata("anonymousInAnonymous.kt")
|
@TestMetadata("anonymousInAnonymous.kt")
|
||||||
public void testAnonymousInAnonymous() throws Exception {
|
public void testAnonymousInAnonymous() throws Exception {
|
||||||
|
|||||||
+34
-41
@@ -5,19 +5,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.transformers
|
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.FirSession
|
||||||
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
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.isInline
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||||
import org.jetbrains.kotlin.fir.render
|
import org.jetbrains.kotlin.fir.render
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
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.resolve.transformers.body.resolve.LocalClassesNavigationInfo
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirCompositeScope
|
import org.jetbrains.kotlin.fir.scopes.FirCompositeScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
@@ -102,23 +97,23 @@ open class FirStatusResolveTransformer(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun transformRegularClass(
|
override fun transformClassContent(
|
||||||
regularClass: FirRegularClass,
|
firClass: FirClass,
|
||||||
data: FirResolvedDeclarationStatus?
|
data: FirResolvedDeclarationStatus?
|
||||||
): FirStatement = whileAnalysing(regularClass) {
|
): FirStatement {
|
||||||
val computationStatus = statusComputationSession.startComputing(regularClass)
|
val computationStatus = statusComputationSession.startComputing(firClass)
|
||||||
forceResolveStatusesOfSupertypes(regularClass)
|
forceResolveStatusesOfSupertypes(firClass)
|
||||||
/*
|
/*
|
||||||
* Status of class may be already calculated if that class was in supertypes of one of previous classes
|
* Status of class may be already calculated if that class was in supertypes of one of previous classes
|
||||||
*/
|
*/
|
||||||
if (computationStatus != StatusComputationSession.StatusComputationStatus.Computed) {
|
if (computationStatus != StatusComputationSession.StatusComputationStatus.Computed) {
|
||||||
regularClass.transformStatus(this, statusResolver.resolveStatus(regularClass, containingClass, isLocal = false))
|
firClass.transformStatus(this, statusResolver.resolveStatus(firClass, containingClass, isLocal = false))
|
||||||
if (regularClass.isInline) {
|
if (firClass is FirRegularClass && firClass.isInline) {
|
||||||
regularClass.valueClassRepresentation = computeValueClassRepresentation(regularClass, session)
|
firClass.valueClassRepresentation = computeValueClassRepresentation(firClass, session)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return transformClass(regularClass, data).also {
|
return transformClass(firClass, data).also {
|
||||||
statusComputationSession.endComputing(regularClass)
|
statusComputationSession.endComputing(firClass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,31 +140,31 @@ open class FirDesignatedStatusResolveTransformer(
|
|||||||
return !designation.classLocated
|
return !designation.classLocated
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun transformRegularClass(
|
override fun transformClassContent(
|
||||||
regularClass: FirRegularClass,
|
firClass: FirClass,
|
||||||
data: FirResolvedDeclarationStatus?
|
data: FirResolvedDeclarationStatus?
|
||||||
): FirStatement = whileAnalysing(regularClass) {
|
): FirStatement = whileAnalysing(firClass) {
|
||||||
if (designation.shouldSkipClass(regularClass)) return regularClass
|
if (designation.shouldSkipClass(firClass)) return firClass
|
||||||
regularClass.symbol.lazyResolveToPhase(FirResolvePhase.TYPES)
|
firClass.symbol.lazyResolveToPhase(FirResolvePhase.TYPES)
|
||||||
val classLocated = designation.classLocated
|
val classLocated = designation.classLocated
|
||||||
/*
|
/*
|
||||||
* In designated status resolve we should resolve status only of target class and it's members
|
* In designated status resolve we should resolve status only of target class and it's members
|
||||||
*/
|
*/
|
||||||
if (classLocated) {
|
if (classLocated) {
|
||||||
assert(regularClass == designation.targetClass)
|
assert(firClass == designation.targetClass)
|
||||||
val computationStatus = statusComputationSession.startComputing(regularClass)
|
val computationStatus = statusComputationSession.startComputing(firClass)
|
||||||
forceResolveStatusesOfSupertypes(regularClass)
|
forceResolveStatusesOfSupertypes(firClass)
|
||||||
if (computationStatus != StatusComputationSession.StatusComputationStatus.Computed) {
|
if (computationStatus != StatusComputationSession.StatusComputationStatus.Computed) {
|
||||||
regularClass.transformStatus(this, statusResolver.resolveStatus(regularClass, containingClass, isLocal = false))
|
firClass.transformStatus(this, statusResolver.resolveStatus(firClass, containingClass, isLocal = false))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (regularClass.status !is FirResolvedDeclarationStatus) {
|
if (firClass.status !is FirResolvedDeclarationStatus) {
|
||||||
regularClass.transformStatus(this, statusResolver.resolveStatus(regularClass, containingClass, isLocal = false))
|
firClass.transformStatus(this, statusResolver.resolveStatus(firClass, containingClass, isLocal = false))
|
||||||
statusComputationSession.computeOnlyClassStatus(regularClass)
|
statusComputationSession.computeOnlyClassStatus(firClass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return transformClass(regularClass, data).also {
|
return transformClass(firClass, data).also {
|
||||||
if (classLocated) statusComputationSession.endComputing(regularClass)
|
if (classLocated) statusComputationSession.endComputing(firClass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -268,25 +263,23 @@ abstract class AbstractFirStatusResolveTransformer(
|
|||||||
return transformDeclaration(typeAlias, data) as FirTypeAlias
|
return transformDeclaration(typeAlias, data) as FirTypeAlias
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract override fun transformRegularClass(
|
override fun transformRegularClass(
|
||||||
regularClass: FirRegularClass,
|
regularClass: FirRegularClass,
|
||||||
data: FirResolvedDeclarationStatus?
|
data: FirResolvedDeclarationStatus?
|
||||||
|
): FirStatement = whileAnalysing(regularClass) {
|
||||||
|
transformClassContent(regularClass, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun transformClassContent(
|
||||||
|
firClass: FirClass,
|
||||||
|
data: FirResolvedDeclarationStatus?
|
||||||
): FirStatement
|
): FirStatement
|
||||||
|
|
||||||
override fun transformAnonymousObject(
|
override fun transformAnonymousObject(
|
||||||
anonymousObject: FirAnonymousObject,
|
anonymousObject: FirAnonymousObject,
|
||||||
data: FirResolvedDeclarationStatus?
|
data: FirResolvedDeclarationStatus?
|
||||||
): FirStatement = whileAnalysing(anonymousObject) {
|
): FirStatement = whileAnalysing(anonymousObject) {
|
||||||
anonymousObject.transformStatus(
|
transformClassContent(anonymousObject, data)
|
||||||
this,
|
|
||||||
FirResolvedDeclarationStatusImpl(
|
|
||||||
anonymousObject.status.visibility,
|
|
||||||
anonymousObject.status.modality ?: Modality.FINAL,
|
|
||||||
EffectiveVisibility.Local
|
|
||||||
)
|
|
||||||
)
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
return transformClass(anonymousObject, data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun transformDeclarationContent(
|
open fun transformDeclarationContent(
|
||||||
@@ -329,7 +322,7 @@ abstract class AbstractFirStatusResolveTransformer(
|
|||||||
} as FirStatement
|
} as FirStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun forceResolveStatusesOfSupertypes(regularClass: FirRegularClass) {
|
protected fun forceResolveStatusesOfSupertypes(regularClass: FirClass) {
|
||||||
for (superTypeRef in regularClass.superTypeRefs) {
|
for (superTypeRef in regularClass.superTypeRefs) {
|
||||||
forceResolveStatusOfCorrespondingClass(superTypeRef)
|
forceResolveStatusOfCorrespondingClass(superTypeRef)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-3
@@ -152,12 +152,15 @@ class FirStatusResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun resolveStatus(
|
fun resolveStatus(
|
||||||
regularClass: FirRegularClass,
|
firClass: FirClass,
|
||||||
containingClass: FirClass?,
|
containingClass: FirClass?,
|
||||||
isLocal: Boolean
|
isLocal: Boolean
|
||||||
): FirResolvedDeclarationStatus {
|
): FirResolvedDeclarationStatus {
|
||||||
val status = regularClass.applyExtensionTransformers { transformStatus(it, regularClass, containingClass, isLocal) }
|
val status = when (firClass) {
|
||||||
return resolveStatus(regularClass, status, containingClass, null, isLocal, emptyList())
|
is FirRegularClass -> firClass.applyExtensionTransformers { transformStatus(it, firClass, containingClass, isLocal) }
|
||||||
|
else -> firClass.status
|
||||||
|
}
|
||||||
|
return resolveStatus(firClass, status, containingClass, null, isLocal, emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resolveStatus(
|
fun resolveStatus(
|
||||||
|
|||||||
Reference in New Issue
Block a user