FIR: Avoid redundant calls to ensureResolved during call resolution

Call ensureResolved only once when creating a candidate
This commit is contained in:
Denis Zharkov
2020-08-26 13:29:41 +03:00
parent bf2fc10cd6
commit 67cc85e02b
8 changed files with 13 additions and 23 deletions
@@ -21,13 +21,11 @@ import org.jetbrains.kotlin.fir.resolve.calls.tower.FirTowerResolver
import org.jetbrains.kotlin.fir.resolve.calls.tower.TowerResolveManager import org.jetbrains.kotlin.fir.resolve.calls.tower.TowerResolveManager
import org.jetbrains.kotlin.fir.resolve.diagnostics.* import org.jetbrains.kotlin.fir.resolve.diagnostics.*
import org.jetbrains.kotlin.fir.resolve.inference.ResolvedCallableReferenceAtom import org.jetbrains.kotlin.fir.resolve.inference.ResolvedCallableReferenceAtom
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.StoreNameReference import org.jetbrains.kotlin.fir.resolve.transformers.StoreNameReference
import org.jetbrains.kotlin.fir.resolve.transformers.StoreReceiver import org.jetbrains.kotlin.fir.resolve.transformers.StoreReceiver
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirExpressionsResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirExpressionsResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolve.transformers.phasedFir
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
@@ -521,7 +519,7 @@ class FirCallResolver(
if (explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() == null) { if (explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() == null) {
if (coneSymbol is FirVariableSymbol) { if (coneSymbol is FirVariableSymbol) {
if (coneSymbol !is FirPropertySymbol || if (coneSymbol !is FirPropertySymbol ||
(coneSymbol.phasedFir() as FirMemberDeclaration).typeParameters.isEmpty() (coneSymbol.fir as FirMemberDeclaration).typeParameters.isEmpty()
) { ) {
return buildResolvedNamedReference { return buildResolvedNamedReference {
this.source = source this.source = source
@@ -208,7 +208,7 @@ fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirReso
private fun BodyResolveComponents.typeFromSymbol(symbol: AbstractFirBasedSymbol<*>, makeNullable: Boolean): FirResolvedTypeRef { private fun BodyResolveComponents.typeFromSymbol(symbol: AbstractFirBasedSymbol<*>, makeNullable: Boolean): FirResolvedTypeRef {
return when (symbol) { return when (symbol) {
is FirCallableSymbol<*> -> { is FirCallableSymbol<*> -> {
val returnTypeRef = returnTypeCalculator.tryCalculateReturnType(symbol.phasedFir) val returnTypeRef = returnTypeCalculator.tryCalculateReturnType(symbol.fir)
if (makeNullable) { if (makeNullable) {
returnTypeRef.withReplacedConeType( returnTypeRef.withReplacedConeType(
returnTypeRef.type.withNullability(ConeNullability.NULLABLE, session.typeContext), returnTypeRef.type.withNullability(ConeNullability.NULLABLE, session.typeContext),
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildConstructedClassTypePa
import org.jetbrains.kotlin.fir.declarations.builder.buildConstructor import org.jetbrains.kotlin.fir.declarations.builder.buildConstructor
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
@@ -68,16 +67,10 @@ internal fun FirScope.processFunctionsAndConstructorsByName(
processConstructorsByName( processConstructorsByName(
name, session, bodyResolveComponents, name, session, bodyResolveComponents,
includeInnerConstructors = includeInnerConstructors, includeInnerConstructors = includeInnerConstructors,
processor = { processor
with(bodyResolveComponents) { it.phasedFir }
processor(it)
}
) )
processFunctionsByName(name) { processFunctionsByName(name, processor)
with(bodyResolveComponents) { it.phasedFir }
processor(it)
}
} }
private fun FirScope.getFirstClassifierOrNull(name: Name): Pair<FirClassifierSymbol<*>, ConeSubstitutor>? { private fun FirScope.getFirstClassifierOrNull(name: Name): Pair<FirClassifierSymbol<*>, ConeSubstitutor>? {
@@ -15,7 +15,6 @@ import kotlin.coroutines.resume
class ResolutionStageRunner(val components: InferenceComponents) { class ResolutionStageRunner(val components: InferenceComponents) {
fun processCandidate(candidate: Candidate, stopOnFirstError: Boolean = true): CandidateApplicability { fun processCandidate(candidate: Candidate, stopOnFirstError: Boolean = true): CandidateApplicability {
val sink = CheckerSinkImpl(components, stopOnFirstError = stopOnFirstError) val sink = CheckerSinkImpl(components, stopOnFirstError = stopOnFirstError)
with (candidate.bodyResolveComponents) { candidate.symbol.phasedFir }
var finished = false var finished = false
sink.continuation = suspend { sink.continuation = suspend {
candidate.callInfo.callKind.resolutionSequence.forEachIndexed { index, stage -> candidate.callInfo.callKind.resolutionSequence.forEachIndexed { index, stage ->
@@ -89,7 +89,7 @@ internal sealed class CheckReceivers : ResolutionStage() {
override fun Candidate.getReceiverType(): ConeKotlinType? { override fun Candidate.getReceiverType(): ConeKotlinType? {
val callableSymbol = symbol as? FirCallableSymbol<*> ?: return null val callableSymbol = symbol as? FirCallableSymbol<*> ?: return null
val callable = with(bodyResolveComponents) { callableSymbol.phasedFir } val callable = callableSymbol.fir
val receiverType = callable.receiverTypeRef?.coneType val receiverType = callable.receiverTypeRef?.coneType
if (receiverType != null) return receiverType if (receiverType != null) return receiverType
val returnTypeRef = callable.returnTypeRef as? FirResolvedTypeRef ?: return null val returnTypeRef = callable.returnTypeRef as? FirResolvedTypeRef ?: return null
@@ -152,7 +152,7 @@ private fun FirExpression.isSuperReferenceExpression(): Boolean {
internal object MapArguments : ResolutionStage() { internal object MapArguments : ResolutionStage() {
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) { override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
val symbol = candidate.symbol as? FirFunctionSymbol<*> ?: return sink.reportApplicability(CandidateApplicability.HIDDEN) val symbol = candidate.symbol as? FirFunctionSymbol<*> ?: return sink.reportApplicability(CandidateApplicability.HIDDEN)
val function = with(candidate.bodyResolveComponents) { symbol.phasedFir } val function = symbol.fir
val mapping = mapArguments(callInfo.arguments, function) val mapping = mapArguments(callInfo.arguments, function)
candidate.argumentMapping = mapping.toArgumentToParameterMapping() candidate.argumentMapping = mapping.toArgumentToParameterMapping()
@@ -212,9 +212,7 @@ internal object CheckCallableReferenceExpectedType : CheckerStage() {
else -> null else -> null
} }
val fir: FirCallableDeclaration<*> = with(candidate.bodyResolveComponents) { val fir: FirCallableDeclaration<*> = candidate.symbol.fir
candidateSymbol.phasedFir
}
val returnTypeRef = candidate.bodyResolveComponents.returnTypeCalculator.tryCalculateReturnType(fir) val returnTypeRef = candidate.bodyResolveComponents.returnTypeCalculator.tryCalculateReturnType(fir)
// If the expected type is a suspend function type and the current argument of interest is a function reference, we need to do // If the expected type is a suspend function type and the current argument of interest is a function reference, we need to do
@@ -5,9 +5,11 @@
package org.jetbrains.kotlin.fir.resolve.calls.tower package org.jetbrains.kotlin.fir.resolve.calls.tower
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
@@ -148,7 +150,7 @@ private class TowerScopeLevelProcessor(
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?, implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
builtInExtensionFunctionReceiverValue: ReceiverValue? builtInExtensionFunctionReceiverValue: ReceiverValue?
) { ) {
with(candidateFactory.bodyResolveComponents) { symbol.phasedFir } symbol.ensureResolved(FirResolvePhase.CONTRACTS, candidateFactory.bodyResolveComponents.session)
// Check explicit extension receiver for default package members // Check explicit extension receiver for default package members
if (symbol is FirNamedFunctionSymbol && dispatchReceiverValue == null && if (symbol is FirNamedFunctionSymbol && dispatchReceiverValue == null &&
(implicitExtensionReceiverValue == null) != (explicitReceiver == null) && (implicitExtensionReceiverValue == null) != (explicitReceiver == null) &&
@@ -87,7 +87,7 @@ class MemberScopeTowerLevel(
if (candidate is FirCallableSymbol<*> && if (candidate is FirCallableSymbol<*> &&
(implicitExtensionInvokeMode || candidate.hasConsistentExtensionReceiver(extensionReceiver)) (implicitExtensionInvokeMode || candidate.hasConsistentExtensionReceiver(extensionReceiver))
) { ) {
val fir = with(bodyResolveComponents) { candidate.phasedFir } val fir = candidate.fir
if ((fir as? FirConstructor)?.isInner == false) { if ((fir as? FirConstructor)?.isInner == false) {
return@processScopeMembers return@processScopeMembers
} }
@@ -71,7 +71,7 @@ class FirCallCompletionResultsWriterTransformer(
qualifiedAccessExpression: T, calleeReference: FirNamedReferenceWithCandidate qualifiedAccessExpression: T, calleeReference: FirNamedReferenceWithCandidate
): T { ): T {
val subCandidate = calleeReference.candidate val subCandidate = calleeReference.candidate
val declaration: FirDeclaration = subCandidate.symbol.phasedFir val declaration: FirDeclaration = subCandidate.symbol.fir as FirDeclaration
val typeArguments = computeTypeArguments(qualifiedAccessExpression, subCandidate) val typeArguments = computeTypeArguments(qualifiedAccessExpression, subCandidate)
val typeRef = if (declaration is FirTypedDeclaration) { val typeRef = if (declaration is FirTypedDeclaration) {
val calculated = typeCalculator.tryCalculateReturnType(declaration) val calculated = typeCalculator.tryCalculateReturnType(declaration)
@@ -417,7 +417,7 @@ class FirCallCompletionResultsWriterTransformer(
private fun computeTypeArgumentTypes( private fun computeTypeArgumentTypes(
candidate: Candidate, candidate: Candidate,
): List<ConeKotlinType> { ): List<ConeKotlinType> {
val declaration = candidate.symbol.phasedFir as? FirCallableMemberDeclaration<*> ?: return emptyList() val declaration = candidate.symbol.fir as? FirCallableMemberDeclaration<*> ?: return emptyList()
return declaration.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) } return declaration.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }
.map { candidate.substitutor.substituteOrSelf(it) } .map { candidate.substitutor.substituteOrSelf(it) }