From ae0ce57b2c46d2792b222732f9598d1a2b8abbb9 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Tue, 15 Mar 2022 11:10:35 +0300 Subject: [PATCH] [FIR] Don't force calculation of return type of overrides during status resolution --- .../transformers/ReturnTypeCalculator.kt | 6 ++++- .../ReturnTypeCalculatorForFullBodyResolve.kt | 2 +- .../fir/scopes/FakeOverrideTypeCalculator.kt | 10 +++---- .../kotlin/fir/scopes/FirOverrideService.kt | 26 ++++++++++++------- .../impl/FirTypeIntersectionScopeContext.kt | 8 ++++-- .../body/resolve/FirImplicitBodyResolve.kt | 2 +- 6 files changed, 34 insertions(+), 20 deletions(-) diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/transformers/ReturnTypeCalculator.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/transformers/ReturnTypeCalculator.kt index cad12df9247..789524a5d48 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/transformers/ReturnTypeCalculator.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/transformers/ReturnTypeCalculator.kt @@ -10,7 +10,11 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef abstract class ReturnTypeCalculator { - abstract fun tryCalculateReturnType(declaration: FirTypedDeclaration): FirResolvedTypeRef + abstract fun tryCalculateReturnTypeOrNull(declaration: FirTypedDeclaration): FirResolvedTypeRef? + + fun tryCalculateReturnType(declaration: FirTypedDeclaration): FirResolvedTypeRef { + return tryCalculateReturnTypeOrNull(declaration)!! + } fun tryCalculateReturnType(symbol: FirCallableSymbol<*>): FirResolvedTypeRef { return tryCalculateReturnType(symbol.fir) diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/transformers/ReturnTypeCalculatorForFullBodyResolve.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/transformers/ReturnTypeCalculatorForFullBodyResolve.kt index 85d00c7ede9..0a6b8bd787c 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/transformers/ReturnTypeCalculatorForFullBodyResolve.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/transformers/ReturnTypeCalculatorForFullBodyResolve.kt @@ -14,7 +14,7 @@ import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef object ReturnTypeCalculatorForFullBodyResolve : ReturnTypeCalculator() { - override fun tryCalculateReturnType(declaration: FirTypedDeclaration): FirResolvedTypeRef { + override fun tryCalculateReturnTypeOrNull(declaration: FirTypedDeclaration): FirResolvedTypeRef? { val returnTypeRef = declaration.returnTypeRef if (returnTypeRef is FirResolvedTypeRef) return returnTypeRef if (declaration.origin.fromSupertypes) { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FakeOverrideTypeCalculator.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FakeOverrideTypeCalculator.kt index a1fe50d9bf2..6ce2021af68 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FakeOverrideTypeCalculator.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FakeOverrideTypeCalculator.kt @@ -16,7 +16,7 @@ import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef abstract class FakeOverrideTypeCalculator { - abstract fun computeReturnType(declaration: FirTypedDeclaration): FirTypeRef + abstract fun computeReturnType(declaration: FirTypedDeclaration): FirTypeRef? object DoNothing : FakeOverrideTypeCalculator() { override fun computeReturnType(declaration: FirTypedDeclaration): FirTypeRef { @@ -25,17 +25,17 @@ abstract class FakeOverrideTypeCalculator { } object Forced : FakeOverrideTypeCalculator() { - override fun computeReturnType(declaration: FirTypedDeclaration): FirResolvedTypeRef { + override fun computeReturnType(declaration: FirTypedDeclaration): FirResolvedTypeRef? { val fakeOverrideSubstitution = declaration.attributes.fakeOverrideSubstitution - ?: return declaration.returnTypeRef as FirResolvedTypeRef + ?: return declaration.returnTypeRef as? FirResolvedTypeRef synchronized(fakeOverrideSubstitution) { if (declaration.attributes.fakeOverrideSubstitution == null) { return declaration.returnTypeRef as FirResolvedTypeRef } - declaration.attributes.fakeOverrideSubstitution = null val (substitutor, baseSymbol) = fakeOverrideSubstitution val baseDeclaration = baseSymbol.fir as FirTypedDeclaration - val baseReturnType = computeReturnType(baseDeclaration).type + val baseReturnType = computeReturnType(baseDeclaration)?.type ?: return null + declaration.attributes.fakeOverrideSubstitution = null val coneType = substitutor.substituteOrSelf(baseReturnType) val returnType = declaration.returnTypeRef.resolvedTypeFromPrototype(coneType) declaration.replaceReturnTypeRef(returnType) diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirOverrideService.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirOverrideService.kt index 68fa6ffc930..fa3d7bfad3d 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirOverrideService.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirOverrideService.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.utils.visibility +import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator import org.jetbrains.kotlin.fir.scopes.impl.buildSubstitutorForOverridesCheck import org.jetbrains.kotlin.fir.scopes.impl.similarFunctionsOrBothProperties import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol @@ -28,7 +29,8 @@ import java.util.* class FirOverrideService(val session: FirSession) : FirSessionComponent { fun > selectMostSpecificInEachOverridableGroup( members: Collection>, - overrideChecker: FirOverrideChecker + overrideChecker: FirOverrideChecker, + returnTypeCalculator: ReturnTypeCalculator ): Collection> { if (members.size <= 1) return members val queue = LinkedList(members) @@ -46,10 +48,10 @@ class FirOverrideService(val session: FirSession) : FirSessionComponent { continue } - val mostSpecific = selectMostSpecificMember(overridableGroup) + val mostSpecific = selectMostSpecificMember(overridableGroup, returnTypeCalculator) overridableGroup.filterNotTo(conflictedHandles) { - isMoreSpecific(mostSpecific.member, it.member) + isMoreSpecific(mostSpecific.member, it.member, returnTypeCalculator) } if (conflictedHandles.isNotEmpty()) { @@ -87,7 +89,10 @@ class FirOverrideService(val session: FirSession) : FirSessionComponent { return result } - fun > selectMostSpecificMember(overridables: Collection>): MemberWithBaseScope { + fun > selectMostSpecificMember( + overridables: Collection>, + returnTypeCalculator: ReturnTypeCalculator + ): MemberWithBaseScope { require(overridables.isNotEmpty()) { "Should have at least one overridable symbol" } if (overridables.size == 1) { return overridables.first() @@ -97,12 +102,12 @@ class FirOverrideService(val session: FirSession) : FirSessionComponent { var transitivelyMostSpecific: MemberWithBaseScope = overridables.first() for (candidate in overridables) { - if (overridables.all { isMoreSpecific(candidate.member, it.member) }) { + if (overridables.all { isMoreSpecific(candidate.member, it.member, returnTypeCalculator) }) { candidates.add(candidate) } - if (isMoreSpecific(candidate.member, transitivelyMostSpecific.member) && - !isMoreSpecific(transitivelyMostSpecific.member, candidate.member) + if (isMoreSpecific(candidate.member, transitivelyMostSpecific.member, returnTypeCalculator) && + !isMoreSpecific(transitivelyMostSpecific.member, candidate.member, returnTypeCalculator) ) { transitivelyMostSpecific = candidate } @@ -123,7 +128,8 @@ class FirOverrideService(val session: FirSession) : FirSessionComponent { private fun isMoreSpecific( a: FirCallableSymbol<*>, - b: FirCallableSymbol<*> + b: FirCallableSymbol<*>, + returnTypeCalculator: ReturnTypeCalculator ): Boolean { val aFir = a.fir val bFir = b.fir @@ -132,8 +138,8 @@ class FirOverrideService(val session: FirSession) : FirSessionComponent { val substitutor = buildSubstitutorForOverridesCheck(aFir, bFir, session) ?: return false // NB: these lines throw CCE in modularized tests when changed to just .coneType (FirImplicitTypeRef) - val aReturnType = a.fir.returnTypeRef.coneTypeSafe()?.let(substitutor::substituteOrSelf) ?: return false - val bReturnType = b.fir.returnTypeRef.coneTypeSafe() ?: return false + val aReturnType = returnTypeCalculator.tryCalculateReturnTypeOrNull(a.fir)?.type?.let(substitutor::substituteOrSelf) ?: return false + val bReturnType = returnTypeCalculator.tryCalculateReturnTypeOrNull(b.fir)?.type ?: return false val typeCheckerState = session.typeContext.newTypeCheckerState( errorTypesEqualToAnything = false, diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScopeContext.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScopeContext.kt index 80712b62aa0..f61973068dd 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScopeContext.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScopeContext.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.isExpect import org.jetbrains.kotlin.fir.declarations.utils.modality import org.jetbrains.kotlin.fir.declarations.utils.visibility import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor +import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve import org.jetbrains.kotlin.fir.scopes.* import org.jetbrains.kotlin.fir.scopes.impl.FirIntersectionOverrideStorage.ContextForIntersectionOverrideConstruction import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScopeContext.ResultOfIntersection @@ -163,7 +164,10 @@ class FirTypeIntersectionScopeContext( }.takeIf { it.isNotEmpty() } ?: extractBothWaysWithPrivate val baseMembersForIntersection = extractedOverrides.calcBaseMembersForIntersectionOverride() if (baseMembersForIntersection.size > 1) { - val (mostSpecific, scopeForMostSpecific) = overrideService.selectMostSpecificMember(baseMembersForIntersection) + val (mostSpecific, scopeForMostSpecific) = overrideService.selectMostSpecificMember( + baseMembersForIntersection, + ReturnTypeCalculatorForFullBodyResolve + ) val intersectionOverrideContext = ContextForIntersectionOverrideConstruction( mostSpecific, this, @@ -216,7 +220,7 @@ class FirTypeIntersectionScopeContext( // we should just take most specific member without creating intersection // A typical sample here is inheritance of the same class in different places of hierarchy if (unwrappedMemberSet.size == 1) { - return listOf(overrideService.selectMostSpecificMember(this)) + return listOf(overrideService.selectMostSpecificMember(this, ReturnTypeCalculatorForFullBodyResolve)) } val baseMembers = mutableSetOf() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt index db73daca162..0d39e8228b4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt @@ -215,7 +215,7 @@ private class ReturnTypeCalculatorWithJump( var outerTowerDataContexts: FirRegularTowerDataContexts? = null - override fun tryCalculateReturnType(declaration: FirTypedDeclaration): FirResolvedTypeRef { + override fun tryCalculateReturnTypeOrNull(declaration: FirTypedDeclaration): FirResolvedTypeRef { if (declaration is FirValueParameter && declaration.returnTypeRef is FirImplicitTypeRef) { // TODO? declaration.transformReturnTypeRef(