From a562f3db3c78a5940ed975429c430be6efe918bc Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 18 Mar 2019 21:51:51 +0300 Subject: [PATCH] FIR: Re-implement call resolver with proper architecture --- .../kotlin/fir/resolve/calls/CallResolver.kt | 540 +++++++++--------- .../transformers/FirBodyResolveTransformer.kt | 129 ++--- .../resolve/expresssions/dispatchReceiver.txt | 4 +- 3 files changed, 341 insertions(+), 332 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallResolver.kt index fcf76a79400..72359754483 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallResolver.kt @@ -7,9 +7,8 @@ package org.jetbrains.kotlin.fir.resolve.calls import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration -import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirFunction -import org.jetbrains.kotlin.fir.render +import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.resolve.scope @@ -22,70 +21,294 @@ import org.jetbrains.kotlin.fir.scopes.processClassifiersByNameWithAction import org.jetbrains.kotlin.fir.service import org.jetbrains.kotlin.fir.symbols.* import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.types.ConeKotlinType -import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.coneTypeUnsafe import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.types.AbstractTypeChecker -import java.util.* -import kotlin.collections.LinkedHashSet +import org.jetbrains.kotlin.utils.addToStdlib.cast -class CallResolver(val typeCalculator: ReturnTypeCalculator) { - lateinit var checkers: List - lateinit var scopes: List +class CallInfo( + val variableAccess: Boolean, + val explicitReceiver: FirExpression?, + val argumentCount: Int +) { - private val names = LinkedHashSet() - private val newNames = mutableSetOf() +} - fun pushName(name: Name) { - newNames += name +interface CheckerSink { + fun reportApplicability(new: CandidateApplicability) +} + + +class CheckerSinkImpl : CheckerSink { + var current = CandidateApplicability.RESOLVED + override fun reportApplicability(new: CandidateApplicability) { + if (new < current) current = new + } +} + +private abstract class Checker { + abstract fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) + +} + +private object MapArguments : Checker() { + override fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) { + val symbol = candidate.symbol as? FirFunctionSymbol ?: return sink.reportApplicability(CandidateApplicability.HIDDEN) + if (symbol.firUnsafe().valueParameters.size != callInfo.argumentCount) { + return sink.reportApplicability(CandidateApplicability.PARAMETER_MAPPING_ERROR) + } } - fun runTowerResolver(): ApplicabilityChecker? { - processedScopes.clear() - newNames.clear() - names.clear() +} - var successChecker: ApplicabilityChecker? = null - checkers.forEach { - it.initNames(this.names) +class Candidate(val symbol: ConeSymbol) {} + + +enum class TowerDataKind { + EMPTY, + TOWER_LEVEL +} + +interface TowerScopeLevel { + + sealed class Token { + object Properties : Token() + + object Functions : Token() + object Objects : Token() + } + + fun processElementsByName( + token: Token, + name: Name, + extensionReceiver: ReceiverValueWithPossibleTypes?, + processor: TowerScopeLevelProcessor + ): ProcessorAction + + interface TowerScopeLevelProcessor { + fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction + } + + object Empty : TowerScopeLevel { + override fun processElementsByName( + token: Token, + name: Name, + extensionReceiver: ReceiverValueWithPossibleTypes?, + processor: TowerScopeLevelProcessor + ): ProcessorAction = ProcessorAction.NEXT + } +} + +interface ReceiverValue { + val type: ConeKotlinType +} + +interface ReceiverValueWithPossibleTypes : ReceiverValue + +class MemberScopeTowerLevel( + val session: FirSession, + val dispatchReceiver: ReceiverValueWithPossibleTypes +) : TowerScopeLevel { + + + private fun processMembers( + output: TowerScopeLevel.TowerScopeLevelProcessor, + takeMembers: FirScope.(processor: (T) -> ProcessorAction) -> ProcessorAction + ): ProcessorAction { + return dispatchReceiver.type.scope(session)?.takeMembers { output.consumeCandidate(it, dispatchReceiver) } ?: ProcessorAction.NEXT + } + + override fun processElementsByName( + token: TowerScopeLevel.Token, + name: Name, + extensionReceiver: ReceiverValueWithPossibleTypes?, + processor: TowerScopeLevel.TowerScopeLevelProcessor + ): ProcessorAction { + return when (token) { + TowerScopeLevel.Token.Properties -> processMembers(processor) { this.processPropertiesByName(name, it.cast()) } + TowerScopeLevel.Token.Functions -> processMembers(processor) { this.processFunctionsByName(name, it.cast()) } + TowerScopeLevel.Token.Objects -> ProcessorAction.NEXT } + } - for ((index, scope) in scopes.asReversed().withIndex()) { - names.addAll(newNames) - newNames.clear() +} - processedScopes.add(scope) +class ScopeTowerLevel( + val session: FirSession, + val scope: FirScope +) : TowerScopeLevel { + override fun processElementsByName( + token: TowerScopeLevel.Token, + name: Name, + extensionReceiver: ReceiverValueWithPossibleTypes?, + processor: TowerScopeLevel.TowerScopeLevelProcessor + ): ProcessorAction { + return when (token) { - names.forEach { name -> - fun process(symbol: ConeSymbol): ProcessorAction { - for (checker in checkers) { - checker.consumeCandidate(index, symbol, this) + TowerScopeLevel.Token.Properties -> scope.processPropertiesByName(name) { processor.consumeCandidate(it as T, null) } + TowerScopeLevel.Token.Functions -> scope.processFunctionsByName(name) { processor.consumeCandidate(it as T, null) } + TowerScopeLevel.Token.Objects -> scope.processClassifiersByNameWithAction(name, FirPosition.OTHER) { + processor.consumeCandidate( + it as T, + null + ) + } + } + } + +} + + +abstract class TowerDataConsumer { + abstract fun consume( + kind: TowerDataKind, + implicitReceiverType: ConeKotlinType?, + towerScopeLevel: TowerScopeLevel, + resultCollector: CandidateCollector + ): ProcessorAction +} + + +fun createVariableConsumer( + session: FirSession, + name: Name, + explicitReceiver: FirExpression?, + explicitReceiverType: FirTypeRef? +): TowerDataConsumer { + return createSimpleConsumer(session, name, TowerScopeLevel.Token.Properties, explicitReceiver, explicitReceiverType) +} + +fun createFunctionConsumer( + session: FirSession, + name: Name, + explicitReceiver: FirExpression?, + explicitReceiverType: FirTypeRef? +): TowerDataConsumer { + return createSimpleConsumer(session, name, TowerScopeLevel.Token.Functions, explicitReceiver, explicitReceiverType) +} + + +fun createSimpleConsumer( + session: FirSession, + name: Name, + token: TowerScopeLevel.Token<*>, + explicitReceiver: FirExpression?, + explicitReceiverType: FirTypeRef? +): TowerDataConsumer { + return if (explicitReceiver != null) { + ExplicitReceiverTowerDataConsumer(session, name, token, object : ReceiverValueWithPossibleTypes { + override val type: ConeKotlinType + get() = explicitReceiverType!!.coneTypeUnsafe() + }) + } else { + NoExplicitReceiverTowerDataConsumer(session, name, token) + } +} + +class ExplicitReceiverTowerDataConsumer( + val session: FirSession, + val name: Name, + val token: TowerScopeLevel.Token, + val explicitReceiver: ReceiverValueWithPossibleTypes +) : TowerDataConsumer() { + + var groupId = 0 + + override fun consume( + kind: TowerDataKind, + implicitReceiverType: ConeKotlinType?, + towerScopeLevel: TowerScopeLevel, + resultCollector: CandidateCollector + ): ProcessorAction { + groupId++ + return when (kind) { + TowerDataKind.EMPTY -> + MemberScopeTowerLevel(session, explicitReceiver).processElementsByName( + token, + name, + null, + object : TowerScopeLevel.TowerScopeLevelProcessor { + override fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction { + resultCollector.consumeCandidate(groupId, symbol) + return ProcessorAction.NEXT + } } - return ProcessorAction.NEXT - } - - scope.processClassifiersByNameWithAction(name, FirPosition.OTHER, ::process) - scope.processPropertiesByName(name, ::process) - scope.processFunctionsByName(name, ::process) - } - - successChecker = checkers.maxBy { it.currentApplicability } - - if (successChecker?.currentApplicability == CandidateApplicability.RESOLVED) { - break - } - + ) + TowerDataKind.TOWER_LEVEL -> + towerScopeLevel.processElementsByName( + token, + name, + explicitReceiver, + object : TowerScopeLevel.TowerScopeLevelProcessor { + override fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction { + resultCollector.consumeCandidate(groupId, symbol) + return ProcessorAction.NEXT + } + } + ) } - - return successChecker } - lateinit var session: FirSession - val processedScopes = mutableListOf() +} + +class NoExplicitReceiverTowerDataConsumer( + val session: FirSession, + val name: Name, + val token: TowerScopeLevel.Token +) : TowerDataConsumer() { + var groupId = 0 + + + override fun consume( + kind: TowerDataKind, + implicitReceiverType: ConeKotlinType?, + towerScopeLevel: TowerScopeLevel, + resultCollector: CandidateCollector + ): ProcessorAction { + groupId++ + return when (kind) { + + TowerDataKind.TOWER_LEVEL -> { + towerScopeLevel.processElementsByName( + token, + name, + null, + object : TowerScopeLevel.TowerScopeLevelProcessor { + override fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction { + resultCollector.consumeCandidate(groupId, symbol) + return ProcessorAction.NEXT + } + } + ) + } + else -> ProcessorAction.NEXT + } + } + +} + +class CallResolver(val typeCalculator: ReturnTypeCalculator, val session: FirSession) { + + var callInfo: CallInfo? = null + + var scopes: List? = null + + fun runTowerResolver(towerDataConsumer: TowerDataConsumer): CandidateCollector { + val collector = CandidateCollector(callInfo!!) + + towerDataConsumer.consume(TowerDataKind.EMPTY, null, TowerScopeLevel.Empty, collector) + + for (scope in scopes!!) { + towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, null, ScopeTowerLevel(session, scope), collector) + } + + return collector + } + } @@ -99,9 +322,7 @@ enum class CandidateApplicability { RESOLVED } - -// TODO: Extract from this transformer -abstract class ApplicabilityChecker { +class CandidateCollector(val callInfo: CallInfo) { val groupNumbers = mutableListOf() val candidates = mutableListOf() @@ -109,35 +330,27 @@ abstract class ApplicabilityChecker { var currentApplicability = CandidateApplicability.HIDDEN - var expectedType: FirTypeRef? = null - var explicitReceiverType: FirTypeRef? = null - fun newDataSet() { groupNumbers.clear() candidates.clear() - expectedType = null currentApplicability = CandidateApplicability.HIDDEN } - protected open fun getApplicability( + protected fun getApplicability( group: Int, - symbol: ConeSymbol, - resolver: CallResolver + symbol: ConeSymbol ): CandidateApplicability { - val declaration = (symbol as? FirBasedSymbol<*>)?.fir - ?: return CandidateApplicability.HIDDEN - declaration as FirDeclaration - if (declaration is FirCallableDeclaration) { - if ((declaration.receiverTypeRef == null) != (explicitReceiverType == null)) return CandidateApplicability.PARAMETER_MAPPING_ERROR - } + val sink = CheckerSinkImpl() - return CandidateApplicability.RESOLVED + MapArguments.check(Candidate(symbol), sink, callInfo) + + return sink.current } - open fun consumeCandidate(group: Int, symbol: ConeSymbol, resolver: CallResolver) { - val applicability = getApplicability(group, symbol, resolver) + fun consumeCandidate(group: Int, symbol: ConeSymbol) { + val applicability = getApplicability(group, symbol) if (applicability > currentApplicability) { groupNumbers.clear() @@ -152,19 +365,13 @@ abstract class ApplicabilityChecker { } } - abstract fun initNames(names: LinkedHashSet) - open fun isSuccessful(index: Int, candidate: ConeSymbol): Boolean { - return true - } - - open fun successCandidates(): List { + fun successCandidates(): List { if (groupNumbers.isEmpty()) return emptyList() val result = mutableListOf() var bestGroup = groupNumbers.first() for ((index, candidate) in candidates.withIndex()) { val group = groupNumbers[index] - if (!isSuccessful(index, candidate)) continue if (bestGroup > group) { bestGroup = group result.clear() @@ -177,195 +384,6 @@ abstract class ApplicabilityChecker { } } -open class VariableApplicabilityChecker(val name: Name) : ApplicabilityChecker() { - override fun initNames(names: LinkedHashSet) { - names.add(name) - } - - override fun consumeCandidate(group: Int, symbol: ConeSymbol, resolver: CallResolver) { - if (symbol !is ConeVariableSymbol) return - if (symbol.callableId.callableName != name) return - super.consumeCandidate(group, symbol, resolver) - } -} - -class VariableInvokeApplicabilityChecker(val variableName: Name) : FunctionApplicabilityChecker(invoke) { - - val variableChecker = object : VariableApplicabilityChecker(variableName) { - override fun isSuccessful(index: Int, candidate: ConeSymbol): Boolean { - return matchedProperties[index] - } - } - private var matchedProperties = BitSet() - private var lookupInvoke = false - - override fun initNames(names: LinkedHashSet) { - names.add(variableName) -// if (lookupInvoke) { -// names.add(name) -// } - } - - private fun isInvokeApplicableOn(propertySymbol: ConeSymbol, invokeSymbol: ConeCallableSymbol): Boolean { - return true //TODO: Actual type-check here - } - - override fun getApplicability( - group: Int, - symbol: ConeSymbol, - resolver: CallResolver - ): CandidateApplicability { - - symbol as ConeCallableSymbol - val declaration = (symbol as? FirBasedSymbol<*>)?.fir - ?: return CandidateApplicability.HIDDEN - declaration as FirDeclaration - - if (declaration is FirFunction) { - if (declaration.valueParameters.size != parameterCount) return CandidateApplicability.PARAMETER_MAPPING_ERROR - } - - var applicable = false - - fun processCandidates(candidates: Iterable>) { - for ((index, candidate) in candidates) { - val invokeApplicableOn = isInvokeApplicableOn(candidate, symbol) - if (invokeApplicableOn) { - applicable = true - } - matchedProperties[index] = invokeApplicableOn - - } - } - - if (group == -1) { - processCandidates(listOf(variableChecker.candidates.withIndex().last())) - } else { - processCandidates(variableChecker.candidates.withIndex()) - } - - if (applicable) { - return CandidateApplicability.RESOLVED - } - return CandidateApplicability.PARAMETER_MAPPING_ERROR - } - - private fun checkSuccess(): Boolean { - return currentApplicability == CandidateApplicability.RESOLVED - } - - - override fun consumeCandidate(group: Int, symbol: ConeSymbol, resolver: CallResolver) { - if (symbol is ConeVariableSymbol && symbol.callableId.callableName == variableName) { - variableChecker.consumeCandidate(group, symbol, resolver) - - val lastCandidate = variableChecker.candidates.lastOrNull() - if (variableChecker.currentApplicability == CandidateApplicability.RESOLVED && lastCandidate == symbol) { - - val receiverScope = - resolver.typeCalculator.tryCalculateReturnType(lastCandidate.firUnsafe()).type - .scope(resolver.session) - - - if (!lookupInvoke) resolver.pushName(invoke) - lookupInvoke = true - - receiverScope?.processFunctionsByName(invoke) { candidate -> - this.consumeCandidate(-1, candidate, resolver) - ProcessorAction.NEXT - } - if (checkSuccess()) return - - for ((index, scope) in resolver.processedScopes.withIndex()) { - scope.processFunctionsByName(invoke) { candidate -> - this.consumeCandidate(index, candidate, resolver) - ProcessorAction.NEXT - } - if (checkSuccess()) return - } - - } - } - - super.consumeCandidate(group, symbol, resolver) - } - - - companion object { - val invoke = Name.identifier("invoke") - } -} - - -class ClassifierApplicabilityChecker(val name: Name) : ApplicabilityChecker() { - override fun initNames(names: LinkedHashSet) { - names.add(name) - } - - override fun consumeCandidate(group: Int, symbol: ConeSymbol, resolver: CallResolver) { - if (symbol !is ConeClassifierSymbol) return - if (symbol.toLookupTag().name != name) return - super.consumeCandidate(group, symbol, resolver) - } - -} - -open class FunctionApplicabilityChecker(val name: Name) : ApplicabilityChecker() { - - var parameterCount = 0 - - override fun initNames(names: LinkedHashSet) { - names.add(name) - } - - lateinit var session: FirSession - - override fun getApplicability( - group: Int, - symbol: ConeSymbol, - resolver: CallResolver - ): CandidateApplicability { - val declaration = symbol.firUnsafe() - - if (declaration is FirFunction && declaration.valueParameters.size != parameterCount) return CandidateApplicability.PARAMETER_MAPPING_ERROR - - - var extensionReceiver = declaration.receiverTypeRef?.coneTypeUnsafe() - var dispatchReceiver = declaration.dispatchReceiverType(session) - - val explicitReceiverType = explicitReceiverType?.coneTypeUnsafe() - - - if (explicitReceiverType != null) { - if (dispatchReceiver != null && explicitReceiverType.isSubtypeOf(dispatchReceiver, session)) { - dispatchReceiver = null - } - if (extensionReceiver != null && explicitReceiverType.isSubtypeOf(extensionReceiver, session)) { - extensionReceiver = null - } - if (extensionReceiver != null || dispatchReceiver != null) return CandidateApplicability.WRONG_RECEIVER - } - - return CandidateApplicability.RESOLVED - } - - fun ConeKotlinType.isSubtypeOf(type: ConeKotlinType, session: FirSession): Boolean { - return try { - AbstractTypeChecker.isSubtypeOf(ConeTypeCheckerContext(true, session), this, type) - } catch (e: IllegalStateException) { - - throw RuntimeException("Sub-typing error: subType = ${this.render()}, superType = ${type.render()}", e) - } - } - - override fun consumeCandidate(group: Int, symbol: ConeSymbol, resolver: CallResolver) { - if (symbol !is ConeFunctionSymbol) return - if (symbol.callableId.callableName != name) return - session = resolver.session - super.consumeCandidate(group, symbol, resolver) - } -} - fun FirCallableDeclaration.dispatchReceiverType(session: FirSession): ConeKotlinType? { val id = (this.symbol as ConeCallableSymbol).callableId.classId ?: return null val symbol = session.service().getClassLikeSymbolByFqName(id) as? FirClassSymbol ?: return null diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt index c90cc4c74ac..19d8a66d949 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt @@ -9,8 +9,6 @@ import com.google.common.collect.LinkedHashMultimap import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* -import org.jetbrains.kotlin.fir.expressions.impl.FirFunctionCallImpl -import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference @@ -101,7 +99,7 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn } FirOperation.SAFE_AS -> { bindingContext[resolved] = - resolved.typeRef.withReplacedConeType( + resolved.typeRef.withReplacedConeType( session, resolved.typeRef.coneTypeUnsafe().withNullability(ConeNullability.NULLABLE) ) @@ -130,26 +128,15 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn val jump = ReturnTypeCalculatorWithJump(session) - private fun runTowerResolver( - checkers: List - ): ApplicabilityChecker? { - val callResolver = CallResolver(jump) - callResolver.scopes = (scopes + localScopes) - callResolver.checkers = checkers - callResolver.session = session - - return callResolver.runTowerResolver() - } - private fun storeTypeFromCallee(access: T) where T : FirQualifiedAccess, T : FirExpression { bindingContext[access] = - when (val newCallee = access.calleeReference) { - is FirErrorNamedReference -> - FirErrorTypeRefImpl(session, access.psi, newCallee.errorReason) - is FirResolvedCallableReference -> - jump.tryCalculateReturnType(newCallee.callableSymbol.firUnsafe()) - else -> return - } + when (val newCallee = access.calleeReference) { + is FirErrorNamedReference -> + FirErrorTypeRefImpl(session, access.psi, newCallee.errorReason) + is FirResolvedCallableReference -> + jump.tryCalculateReturnType(newCallee.callableSymbol.firUnsafe()) + else -> return + } } override fun transformQualifiedAccessExpression( @@ -170,18 +157,21 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn qualifiedAccessExpression.explicitReceiver?.visitNoTransform(this, null) - val checkers = listOf(VariableApplicabilityChecker(callee.name).apply { - expectedType = data as FirTypeRef? - explicitReceiverType = qualifiedAccessExpression.explicitReceiver?.resultType - }) + val receiver = qualifiedAccessExpression.explicitReceiver - val result = runTowerResolver(checkers) - if (result != null) { - val resultExpression = qualifiedAccessExpression.transformCalleeReference(this, result.successCandidates()) - storeTypeFromCallee(resultExpression as FirQualifiedAccessExpression) - return resultExpression.compose() - } - return qualifiedAccessExpression.compose() + //val checkers = listOf(VariableApplicabilityChecker(callee.name)) + + val info = CallInfo(true, receiver, 0) + val resolver = CallResolver(jump, session) + resolver.callInfo = info + resolver.scopes = (scopes + localScopes).asReversed() + + val consumer = createVariableConsumer(session, callee.name, qualifiedAccessExpression.explicitReceiver, qualifiedAccessExpression.explicitReceiver?.resultType) + val result = resolver.runTowerResolver(consumer) + val successCandidates = result.successCandidates() + val resultExpression = qualifiedAccessExpression.transformCalleeReference(this, successCandidates) + storeTypeFromCallee(resultExpression as FirQualifiedAccessExpression) + return resultExpression.compose() } override fun transformFunctionCall(functionCall: FirFunctionCall, data: Any?): CompositeTransformResult { @@ -197,46 +187,47 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn val receiver = functionCall.explicitReceiver val arguments = functionCall.arguments - val checkers = listOf(FunctionApplicabilityChecker(name).apply { - expectedType = expectedTypeRef - explicitReceiverType = receiver?.resultType - parameterCount = arguments.size - }, VariableInvokeApplicabilityChecker(name).apply { - expectedType = expectedTypeRef - variableChecker.apply { - expectedType = expectedTypeRef - explicitReceiverType = receiver?.resultType - } - parameterCount = arguments.size - }) + + val info = CallInfo(false, receiver, arguments.size) + val resolver = CallResolver(jump, session) + resolver.callInfo = info + resolver.scopes = (scopes + localScopes).asReversed() - val result = runTowerResolver(checkers) - val resultExpression = when (result) { - is VariableInvokeApplicabilityChecker -> { - FirFunctionCallImpl(functionCall.session, functionCall.psi, safe = functionCall.safe).apply { - calleeReference = - functionCall.calleeReference.transformSingle(this@FirBodyResolveTransformer, result.successCandidates()) - explicitReceiver = - FirQualifiedAccessExpressionImpl( - functionCall.session, - functionCall.calleeReference.psi, - functionCall.safe - ).apply { - calleeReference = createResolvedNamedReference( - functionCall.calleeReference, - result.variableChecker.successCandidates() as List - ) - explicitReceiver = functionCall.explicitReceiver - } - } - } - is ApplicabilityChecker -> { - functionCall.transformCalleeReference(this, result.successCandidates()) - } - else -> functionCall - } + val consumer = createFunctionConsumer(session, name, receiver, receiver?.resultType) + val result = resolver.runTowerResolver(consumer) + val successCandidates = result.successCandidates() + +// fun isInvoke() +// +// val resultExpression = +// +// when { +// successCandidates.singleOrNull() as? ConeCallableSymbol -> { +// FirFunctionCallImpl(functionCall.session, functionCall.psi, safe = functionCall.safe).apply { +// calleeReference = +// functionCall.calleeReference.transformSingle(this@FirBodyResolveTransformer, result.successCandidates()) +// explicitReceiver = +// FirQualifiedAccessExpressionImpl( +// functionCall.session, +// functionCall.calleeReference.psi, +// functionCall.safe +// ).apply { +// calleeReference = createResolvedNamedReference( +// functionCall.calleeReference, +// result.variableChecker.successCandidates() as List +// ) +// explicitReceiver = functionCall.explicitReceiver +// } +// } +// } +// is ApplicabilityChecker -> { +// functionCall.transformCalleeReference(this, result.successCandidates()) +// } +// else -> functionCall +// } + val resultExpression = functionCall.transformCalleeReference(this, successCandidates) storeTypeFromCallee(resultExpression as FirFunctionCall) return resultExpression.compose() diff --git a/compiler/fir/resolve/testData/resolve/expresssions/dispatchReceiver.txt b/compiler/fir/resolve/testData/resolve/expresssions/dispatchReceiver.txt index 9142951cbc3..6277e7370b5 100644 --- a/compiler/fir/resolve/testData/resolve/expresssions/dispatchReceiver.txt +++ b/compiler/fir/resolve/testData/resolve/expresssions/dispatchReceiver.txt @@ -10,8 +10,8 @@ FILE: dispatchReceiver.kt public get(): R|Base| public set(value: R|Base|): R|kotlin/Unit| - public final fun check(): { - ^check R|/My.delegate|.R|/My.check|() + public final fun check(): R|kotlin/Unit| { + ^check R|/My.delegate|.R|/Base.check|() } }