diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirPsiTypeProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirPsiTypeProvider.kt index 58d9df37470..2be53e8d10d 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirPsiTypeProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirPsiTypeProvider.kt @@ -73,26 +73,34 @@ private fun ConeKotlinType.simplifyType( currentType = currentType.fullyExpandedType(session) currentType = currentType.upperBoundIfFlexible() currentType = substitutor.substituteOrSelf(currentType) - if (shouldHideLocalType(visibilityForApproximation, isInlineFunction)) { - val localTypes: List = if (isLocal(session)) listOf(this) else { - typeArguments.mapNotNull { - if (it is ConeKotlinTypeProjection && it.type.isLocal(session)) { - it.type - } else null - } - } - val unavailableLocalTypes = localTypes.filterNot { it.isLocalButAvailableAtPosition(session, useSitePosition) } - // Need to approximate if there are local types that are not available in this scope - val needsApproximation = localTypes.isNotEmpty() && unavailableLocalTypes.isNotEmpty() - if (needsApproximation) { - // TODO: can we approximate local types in type arguments *selectively* ? - currentType = PublicTypeApproximator.approximateTypeToPublicDenotable(currentType, session) ?: currentType - } - } + val needLocalTypeApproximation = needLocalTypeApproximation(visibilityForApproximation, isInlineFunction, session, useSitePosition) + // TODO: can we approximate local types in type arguments *selectively* ? + currentType = PublicTypeApproximator.approximateTypeToPublicDenotable(currentType, session, needLocalTypeApproximation) + ?: currentType + } while (oldType !== currentType) return currentType } +private fun ConeKotlinType.needLocalTypeApproximation( + visibilityForApproximation: Visibility, + isInlineFunction: Boolean, + session: FirSession, + useSitePosition: PsiElement +): Boolean { + if (!shouldHideLocalType(visibilityForApproximation, isInlineFunction)) return false + val localTypes: List = if (isLocal(session)) listOf(this) else { + typeArguments.mapNotNull { + if (it is ConeKotlinTypeProjection && it.type.isLocal(session)) { + it.type + } else null + } + } + val unavailableLocalTypes = localTypes.filterNot { it.isLocalButAvailableAtPosition(session, useSitePosition) } + // Need to approximate if there are local types that are not available in this scope + return localTypes.isNotEmpty() && unavailableLocalTypes.isNotEmpty() +} + // Mimic FirDeclaration.visibilityForApproximation private val PsiElement.visibilityForApproximation: Visibility get() { diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirTypeProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirTypeProvider.kt index 7f609781ea4..207259868b6 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirTypeProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirTypeProvider.kt @@ -59,7 +59,8 @@ internal class KtFirTypeProvider( val coneType = type.coneType val approximatedConeType = PublicTypeApproximator.approximateTypeToPublicDenotable( coneType, - rootModuleSession + rootModuleSession, + approximateLocalTypes = true, ) return approximatedConeType?.asKtType() diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/renderer/FirIdeRenderer.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/renderer/FirIdeRenderer.kt index 801f9fa2c36..8b968812e6f 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/renderer/FirIdeRenderer.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/renderer/FirIdeRenderer.kt @@ -50,7 +50,7 @@ internal class FirIdeRenderer private constructor( require(firRef is FirResolvedTypeRef) val approximatedIfNeeded = approximate.ifTrue { - PublicTypeApproximator.approximateTypeToPublicDenotable(firRef.coneType, session) + PublicTypeApproximator.approximateTypeToPublicDenotable(firRef.coneType, session, approximateLocalTypes = true) } ?: firRef.coneType val annotations = if (RendererModifier.ANNOTATIONS in options.modifiers) { firRef.annotations diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/PublicTypeApproximator.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/PublicTypeApproximator.kt index 4f0637139bc..0dc48f3274a 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/PublicTypeApproximator.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/PublicTypeApproximator.kt @@ -14,17 +14,19 @@ internal object PublicTypeApproximator { fun approximateTypeToPublicDenotable( type: ConeKotlinType, session: FirSession, + approximateLocalTypes: Boolean ): ConeKotlinType? { val approximator = session.typeApproximator - return approximator.approximateToSuperType(type, PublicApproximatorConfiguration) + return approximator.approximateToSuperType(type, PublicApproximatorConfiguration(approximateLocalTypes)) } - private object PublicApproximatorConfiguration : TypeApproximatorConfiguration.AllFlexibleSameValue() { + private class PublicApproximatorConfiguration( + override val localTypes: Boolean + ) : TypeApproximatorConfiguration.AllFlexibleSameValue() { override val allFlexible: Boolean get() = false override val errorType: Boolean get() = true override val definitelyNotNullType: Boolean get() = false override val integerLiteralType: Boolean get() = true override val intersectionTypesInContravariantPositions: Boolean get() = true - override val localTypes: Boolean get() = true } }