[FIR] make FirJavaClass.superTypes to be lazily enhanced
This should solve the problem with deadlocks/performance in the K2 IDE
This is a temporary solution until the ^KT-55387 is properly fixed
^KT-55387
^KT-54890
diff --git a/.idea/dictionaries/darthorimar.xml b/.idea/dictionaries/darthorimar.xml
new file mode 100644
index 0000000..1cfd3d9
--- /dev/null
+++ b/.idea/dictionaries/darthorimar.xml
@@ -0,0 +1,7 @@
+<component name="ProjectDictionaryState">
+ <dictionary name="darthorimar">
+ <words>
+ <w>unenhnanced</w>
+ </words>
+ </dictionary>
+</component>
\ No newline at end of file
diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaFacade.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaFacade.kt
index ff2ebaf..cf0026e 100644
--- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaFacade.kt
+++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaFacade.kt
@@ -12,7 +12,6 @@
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.*
-import org.jetbrains.kotlin.fir.analysis.checkers.typeParameterSymbols
import org.jetbrains.kotlin.fir.caches.createCache
import org.jetbrains.kotlin.fir.caches.firCachesFactory
import org.jetbrains.kotlin.fir.caches.getValue
@@ -24,21 +23,15 @@
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.utils.effectiveVisibility
import org.jetbrains.kotlin.fir.declarations.utils.modality
-import org.jetbrains.kotlin.fir.expressions.FirConstExpression
-import org.jetbrains.kotlin.fir.expressions.classId
import org.jetbrains.kotlin.fir.java.declarations.*
import org.jetbrains.kotlin.fir.java.enhancement.FirSignatureEnhancement
import org.jetbrains.kotlin.fir.resolve.constructType
import org.jetbrains.kotlin.fir.resolve.defaultType
-import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
-import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
-import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
-import org.jetbrains.kotlin.load.java.FakePureImplementationsProvider
import org.jetbrains.kotlin.load.java.JavaClassFinder
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.java.structure.*
@@ -181,57 +174,13 @@
// 1. Resolve annotations
// 2. Enhance type parameter bounds - may refer to each other, take default nullability from annotations
- // 3. Enhance super types - may refer to type parameter bounds, take default nullability from annotations
+ // 3. (will happen lazily in FirJavaClass.superTypeRefs) Enhance super types - may refer to type parameter bounds, take default nullability from annotations
+
firJavaClass.setAnnotationsFromJava(session, javaClass, javaTypeParameterStack)
-
enhancement.enhanceTypeParameterBoundsAfterFirstRound(firJavaClass.typeParameters, initialBounds)
-
- val enhancedSuperTypes = buildList {
- val purelyImplementedSupertype = firJavaClass.getPurelyImplementedSupertype()
- val purelyImplementedSupertypeClassId = purelyImplementedSupertype?.classId
- firJavaClass.superTypeRefs.mapNotNullTo(this) { superType ->
- enhancement.enhanceSuperType(superType).takeUnless {
- purelyImplementedSupertypeClassId != null && it.coneType.classId == purelyImplementedSupertypeClassId
- }
- }
- purelyImplementedSupertype?.let {
- add(buildResolvedTypeRef { type = it })
- }
- }
- firJavaClass.replaceSuperTypeRefs(enhancedSuperTypes)
firJavaClass.replaceDeprecationsProvider(firJavaClass.getDeprecationsProvider(session.firCachesFactory))
- return firJavaClass
- }
- private fun FirJavaClass.getPurelyImplementedSupertype(): ConeKotlinType? {
- val purelyImplementedClassIdFromAnnotation = annotations
- .firstOrNull { it.classId?.asSingleFqName() == JvmAnnotationNames.PURELY_IMPLEMENTS_ANNOTATION }
- ?.let { (it.argumentMapping.mapping.values.firstOrNull() as? FirConstExpression<*>) }
- ?.let { it.value as? String }
- ?.takeIf { it.isNotBlank() && isValidJavaFqName(it) }
- ?.let { ClassId.topLevel(FqName(it)) }
- val purelyImplementedClassId = purelyImplementedClassIdFromAnnotation
- ?: FakePureImplementationsProvider.getPurelyImplementedInterface(symbol.classId)
- ?: return null
- val superTypeSymbol = session.symbolProvider.getClassLikeSymbolByClassId(purelyImplementedClassId) ?: return null
- val superTypeParameterSymbols = superTypeSymbol.typeParameterSymbols ?: return null
- val typeParameters = this.typeParameters
- val supertypeParameterCount = superTypeParameterSymbols.size
- val typeParameterCount = typeParameters.size
- val parametersAsTypeProjections = when {
- typeParameterCount == supertypeParameterCount ->
- typeParameters.map { ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(it.symbol), isNullable = false) }
- typeParameterCount == 1 && supertypeParameterCount > 1 && purelyImplementedClassIdFromAnnotation == null -> {
- val projection = ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(typeParameters.first().symbol), isNullable = false)
- (1..supertypeParameterCount).map { projection }
- }
- else -> return null
- }
- return ConeClassLikeTypeImpl(
- ConeClassLikeLookupTagImpl(purelyImplementedClassId),
- parametersAsTypeProjections.toTypedArray(),
- isNullable = false
- )
+ return firJavaClass
}
private fun createFirJavaClass(
diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt
index ca3cfb8..baa08ca 100644
--- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt
+++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt
@@ -19,6 +19,7 @@
import org.jetbrains.kotlin.fir.declarations.builder.FirRegularClassBuilder
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
+import org.jetbrains.kotlin.fir.java.enhancement.FirSignatureEnhancement
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
import org.jetbrains.kotlin.fir.scopes.FirScopeProvider
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
@@ -44,7 +45,7 @@
override val declarations: MutableList<FirDeclaration>,
override val scopeProvider: FirScopeProvider,
override val symbol: FirRegularClassSymbol,
- override val superTypeRefs: MutableList<FirTypeRef>,
+ private val unenhnancedSuperTypes: List<FirTypeRef>,
override val typeParameters: MutableList<FirTypeParameterRef>,
internal val javaPackage: JavaPackage?,
val javaTypeParameterStack: JavaTypeParameterStack,
@@ -63,9 +64,14 @@
override val attributes: FirDeclarationAttributes = FirDeclarationAttributes()
+ // TODO: the lazy superTypeRefs is a workaround for KT-55387, some non-lazy solution should probably be used instead
+ override val superTypeRefs: List<FirTypeRef> by lazy {
+ val enhancement = FirSignatureEnhancement(this@FirJavaClass, moduleData.session, overridden = { emptyList() })
+ enhancement.enhanceSuperTypes(unenhnancedSuperTypes)
+ }
+
override fun replaceSuperTypeRefs(newSuperTypeRefs: List<FirTypeRef>) {
- superTypeRefs.clear()
- superTypeRefs.addAll(newSuperTypeRefs)
+ error("${::replaceSuperTypeRefs.name} should not be called for ${this::class.simpleName}, ${superTypeRefs::class.simpleName} is lazily calulated")
}
override fun replaceResolvePhase(newResolvePhase: FirResolvePhase) {
@@ -101,7 +107,6 @@
}
override fun <D> transformSuperTypeRefs(transformer: FirTransformer<D>, data: D): FirRegularClass {
- superTypeRefs.transformInplace(transformer, data)
return this
}
@@ -152,6 +157,7 @@
@OptIn(FirImplementationDetail::class)
override fun build(): FirJavaClass {
+ @Suppress("UNCHECKED_CAST")
return FirJavaClass(
source,
moduleData,
diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt
index a9e95f8..6860e62 100644
--- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt
+++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt
@@ -10,6 +10,7 @@
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.*
+import org.jetbrains.kotlin.fir.analysis.checkers.typeParameterSymbols
import org.jetbrains.kotlin.fir.caches.FirCache
import org.jetbrains.kotlin.fir.caches.FirCachesFactory
import org.jetbrains.kotlin.fir.caches.createCache
@@ -25,26 +26,31 @@
import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
+import org.jetbrains.kotlin.fir.expressions.FirConstExpression
+import org.jetbrains.kotlin.fir.expressions.classId
import org.jetbrains.kotlin.fir.java.FirJavaTypeConversionMode
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
import org.jetbrains.kotlin.fir.java.declarations.*
import org.jetbrains.kotlin.fir.java.resolveIfJavaType
import org.jetbrains.kotlin.fir.java.symbols.FirJavaOverriddenSyntheticPropertySymbol
import org.jetbrains.kotlin.fir.java.toConeKotlinTypeProbablyFlexible
+import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptor
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
+import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
+import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
import org.jetbrains.kotlin.load.java.AnnotationQualifierApplicabilityType
+import org.jetbrains.kotlin.load.java.FakePureImplementationsProvider
import org.jetbrains.kotlin.load.java.JavaTypeQualifiersByElementType
+import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.java.typeEnhancement.*
import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents
-import org.jetbrains.kotlin.name.CallableId
-import org.jetbrains.kotlin.name.FqNameUnsafe
-import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeParameterMarker
@@ -442,7 +448,55 @@
AnnotationQualifierApplicabilityType.TYPE_PARAMETER_BOUNDS, contextQualifiers
).enhance(bound, emptyList(), FirJavaTypeConversionMode.TYPE_PARAMETER_BOUND_AFTER_FIRST_ROUND)
- fun enhanceSuperType(type: FirTypeRef): FirTypeRef =
+
+ fun enhanceSuperTypes(unenhnancedSuperTypes: List<FirTypeRef>): List<FirTypeRef> {
+ val purelyImplementedSupertype = getPurelyImplementedSupertype(moduleData.session)
+ val purelyImplementedSupertypeClassId = purelyImplementedSupertype?.classId
+ return buildList {
+ unenhnancedSuperTypes.mapNotNullTo(this) { superType ->
+ enhanceSuperType(superType).takeUnless {
+ purelyImplementedSupertypeClassId != null && it.coneType.classId == purelyImplementedSupertypeClassId
+ }
+ }
+ purelyImplementedSupertype?.let {
+ add(buildResolvedTypeRef { type = it })
+ }
+ }
+ }
+
+ private fun getPurelyImplementedSupertype(session: FirSession): ConeKotlinType? {
+ val purelyImplementedClassIdFromAnnotation = owner.annotations
+ .firstOrNull { it.classId?.asSingleFqName() == JvmAnnotationNames.PURELY_IMPLEMENTS_ANNOTATION }
+ ?.let { (it.argumentMapping.mapping.values.firstOrNull() as? FirConstExpression<*>) }
+ ?.let { it.value as? String }
+ ?.takeIf { it.isNotBlank() && isValidJavaFqName(it) }
+ ?.let { ClassId.topLevel(FqName(it)) }
+ val purelyImplementedClassId = purelyImplementedClassIdFromAnnotation
+ ?: FakePureImplementationsProvider.getPurelyImplementedInterface(owner.symbol.classId)
+ ?: return null
+ val superTypeSymbol = session.symbolProvider.getClassLikeSymbolByClassId(purelyImplementedClassId) ?: return null
+ val superTypeParameterSymbols = superTypeSymbol.typeParameterSymbols ?: return null
+ val typeParameters = owner.typeParameters
+ val supertypeParameterCount = superTypeParameterSymbols.size
+ val typeParameterCount = typeParameters.size
+ val parametersAsTypeProjections = when {
+ typeParameterCount == supertypeParameterCount ->
+ typeParameters.map { ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(it.symbol), isNullable = false) }
+ typeParameterCount == 1 && supertypeParameterCount > 1 && purelyImplementedClassIdFromAnnotation == null -> {
+ val projection = ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(typeParameters.first().symbol), isNullable = false)
+ (1..supertypeParameterCount).map { projection }
+ }
+ else -> return null
+ }
+ return ConeClassLikeTypeImpl(
+ ConeClassLikeLookupTagImpl(purelyImplementedClassId),
+ parametersAsTypeProjections.toTypedArray(),
+ isNullable = false
+ )
+ }
+
+
+ private fun enhanceSuperType(type: FirTypeRef): FirTypeRef =
EnhancementSignatureParts(
session, typeQualifierResolver, null, isCovariant = false, forceOnlyHeadTypeConstructor = false,
AnnotationQualifierApplicabilityType.TYPE_USE, contextQualifiers
diff --git a/compiler/testData/diagnostics/tests/platformTypes/rawTypes/kt47459.kt b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/kt47459.kt
index 0b2ce15..f31435a 100644
--- a/compiler/testData/diagnostics/tests/platformTypes/rawTypes/kt47459.kt
+++ b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/kt47459.kt
@@ -1,4 +1,3 @@
-// FIR_DISABLE_LAZY_RESOLVE_CHECKS
// FIR_IDENTICAL
// FILE: MapObjectManager.java
abstract class MapObjectManager<C extends MapObjectManager.Collection> {
diff --git a/compiler/testData/diagnostics/tests/platformTypes/rawTypes/smartCastToClassWithRawSupertype.kt b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/smartCastToClassWithRawSupertype.kt
index 2afe731..b5f72f9 100644
--- a/compiler/testData/diagnostics/tests/platformTypes/rawTypes/smartCastToClassWithRawSupertype.kt
+++ b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/smartCastToClassWithRawSupertype.kt
@@ -1,4 +1,3 @@
-// FIR_DISABLE_LAZY_RESOLVE_CHECKS
// FIR_IDENTICAL
// SKIP_TXT
// !DIAGNOSTICS: -UNUSED_VARIABLE