FIR invoke resolve: remove redundant candidates

This commit is contained in:
Mikhail Glukhikh
2019-12-26 17:20:07 +03:00
parent f47c3f0f5a
commit a54ef3e427
4 changed files with 18 additions and 43 deletions
@@ -173,7 +173,7 @@ class ExplicitReceiverTowerDataConsumer<T : AbstractFirBasedSymbol<*>>(
MemberScopeTowerLevel( MemberScopeTowerLevel(
session, resultCollector.components, explicitReceiver, session, resultCollector.components, explicitReceiver,
implicitExtensionReceiver = (towerScopeLevel as? TowerScopeLevel.OnlyImplicitReceiver)?.implicitReceiverValue, implicitExtensionReceiver = (towerScopeLevel as? TowerScopeLevel.OnlyImplicitReceiver)?.implicitReceiverValue,
invokeOnly = towerScopeLevel is TowerScopeLevel.OnlyImplicitReceiver, implicitExtensionInvokeMode = towerScopeLevel is TowerScopeLevel.OnlyImplicitReceiver,
scopeSession = candidateFactory.bodyResolveComponents.scopeSession scopeSession = candidateFactory.bodyResolveComponents.scopeSession
).processElementsByName( ).processElementsByName(
token, token,
@@ -10,9 +10,7 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirImportImpl import org.jetbrains.kotlin.fir.declarations.impl.FirImportImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedImportImpl import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedImportImpl
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
@@ -49,7 +47,7 @@ interface TowerScopeLevel {
symbol: T, symbol: T,
dispatchReceiverValue: ClassDispatchReceiverValue?, dispatchReceiverValue: ClassDispatchReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?, implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
builtInExtensionFunctionReceiverValue: ReceiverValue? builtInExtensionFunctionReceiverValue: ReceiverValue? = null
): ProcessorAction ): ProcessorAction
} }
@@ -97,28 +95,28 @@ class MemberScopeTowerLevel(
val bodyResolveComponents: BodyResolveComponents, val bodyResolveComponents: BodyResolveComponents,
val dispatchReceiver: ReceiverValue, val dispatchReceiver: ReceiverValue,
val implicitExtensionReceiver: ImplicitReceiverValue<*>? = null, val implicitExtensionReceiver: ImplicitReceiverValue<*>? = null,
val invokeOnly: Boolean = false, val implicitExtensionInvokeMode: Boolean = false,
val scopeSession: ScopeSession val scopeSession: ScopeSession
) : SessionBasedTowerLevel(session) { ) : SessionBasedTowerLevel(session) {
private fun <T : AbstractFirBasedSymbol<*>> processMembers( private fun <T : AbstractFirBasedSymbol<*>> processMembers(
output: TowerScopeLevel.TowerScopeLevelProcessor<T>, output: TowerScopeLevel.TowerScopeLevelProcessor<T>,
explicitExtensionReceiver: ExpressionReceiverValue?, explicitExtensionReceiver: ExpressionReceiverValue?,
isInvoke: Boolean,
processScopeMembers: FirScope.(processor: (T) -> ProcessorAction) -> ProcessorAction processScopeMembers: FirScope.(processor: (T) -> ProcessorAction) -> ProcessorAction
): ProcessorAction { ): ProcessorAction {
if (implicitExtensionReceiver != null && explicitExtensionReceiver != null) return ProcessorAction.NEXT if (implicitExtensionReceiver != null && explicitExtensionReceiver != null) return ProcessorAction.NEXT
val extensionReceiver = implicitExtensionReceiver ?: explicitExtensionReceiver val extensionReceiver = implicitExtensionReceiver ?: explicitExtensionReceiver
val scope = dispatchReceiver.scope(session, scopeSession) ?: return ProcessorAction.NEXT val scope = dispatchReceiver.scope(session, scopeSession) ?: return ProcessorAction.NEXT
if (scope.processScopeMembers { candidate -> if (scope.processScopeMembers { candidate ->
if (candidate is FirCallableSymbol<*> && (invokeOnly || candidate.hasConsistentExtensionReceiver(extensionReceiver))) { if (candidate is FirCallableSymbol<*> &&
(implicitExtensionInvokeMode || candidate.hasConsistentExtensionReceiver(extensionReceiver))
) {
// NB: we do not check dispatchReceiverValue != null here, // NB: we do not check dispatchReceiverValue != null here,
// because of objects & constructors (see comments in dispatchReceiverValue() implementation) // because of objects & constructors (see comments in dispatchReceiverValue() implementation)
val dispatchReceiverValue = candidate.dispatchReceiverValue() val dispatchReceiverValue = candidate.dispatchReceiverValue()
if (invokeOnly) { if (implicitExtensionInvokeMode) {
if (output.consumeCandidate( if (output.consumeCandidate(
candidate, dispatchReceiverValue, candidate, dispatchReceiverValue,
implicitExtensionReceiverValue = implicitExtensionReceiver, implicitExtensionReceiverValue = implicitExtensionReceiver
builtInExtensionFunctionReceiverValue = null
).stop() ).stop()
) { ) {
ProcessorAction.STOP ProcessorAction.STOP
@@ -130,27 +128,7 @@ class MemberScopeTowerLevel(
) )
} }
} else { } else {
val builtInFunctionReceiverExpression = output.consumeCandidate(candidate, dispatchReceiverValue, implicitExtensionReceiver, null)
if (!isInvoke || dispatchReceiver !is ExpressionReceiverValue) null
else (dispatchReceiver.explicitReceiverExpression as? FirQualifiedAccess)?.extensionReceiver
if (dispatchReceiver !is ExpressionReceiverValue ||
builtInFunctionReceiverExpression == null ||
builtInFunctionReceiverExpression is FirNoReceiverExpression
) {
output.consumeCandidate(candidate, dispatchReceiverValue, implicitExtensionReceiver, null)
} else {
if (output.consumeCandidate(candidate, dispatchReceiverValue, implicitExtensionReceiver, null).stop()) {
ProcessorAction.STOP
} else {
output.consumeCandidate(
candidate, dispatchReceiverValue,
implicitExtensionReceiverValue = null,
builtInExtensionFunctionReceiverValue = ExpressionReceiverValue(
builtInFunctionReceiverExpression, dispatchReceiver.typeProvider
)
)
}
}
} }
} else if (candidate is FirClassLikeSymbol<*>) { } else if (candidate is FirClassLikeSymbol<*>) {
output.consumeCandidate(candidate, null, implicitExtensionReceiver, null) output.consumeCandidate(candidate, null, implicitExtensionReceiver, null)
@@ -172,18 +150,18 @@ class MemberScopeTowerLevel(
processor: TowerScopeLevel.TowerScopeLevelProcessor<T> processor: TowerScopeLevel.TowerScopeLevelProcessor<T>
): ProcessorAction { ): ProcessorAction {
val isInvoke = name == OperatorNameConventions.INVOKE && token == TowerScopeLevel.Token.Functions val isInvoke = name == OperatorNameConventions.INVOKE && token == TowerScopeLevel.Token.Functions
if (invokeOnly && !isInvoke) { if (implicitExtensionInvokeMode && !isInvoke) {
return ProcessorAction.NEXT return ProcessorAction.NEXT
} }
val explicitExtensionReceiver = if (dispatchReceiver == explicitReceiver) null else explicitReceiver val explicitExtensionReceiver = if (dispatchReceiver == explicitReceiver) null else explicitReceiver
return when (token) { return when (token) {
TowerScopeLevel.Token.Properties -> processMembers(processor, explicitExtensionReceiver, isInvoke) { symbol -> TowerScopeLevel.Token.Properties -> processMembers(processor, explicitExtensionReceiver) { symbol ->
this.processPropertiesByName(name, symbol.cast()) this.processPropertiesByName(name, symbol.cast())
} }
TowerScopeLevel.Token.Functions -> processMembers(processor, explicitExtensionReceiver, isInvoke) { symbol -> TowerScopeLevel.Token.Functions -> processMembers(processor, explicitExtensionReceiver) { symbol ->
this.processFunctionsAndConstructorsByName(name, session, bodyResolveComponents, symbol.cast()) this.processFunctionsAndConstructorsByName(name, session, bodyResolveComponents, symbol.cast())
} }
TowerScopeLevel.Token.Objects -> processMembers(processor, explicitExtensionReceiver, isInvoke) { symbol -> TowerScopeLevel.Token.Objects -> processMembers(processor, explicitExtensionReceiver) { symbol ->
this.processClassifiersByName(name, symbol.cast()) this.processClassifiersByName(name, symbol.cast())
} }
} }
@@ -232,8 +210,7 @@ class ScopeTowerLevel(
} }
processor.consumeCandidate( processor.consumeCandidate(
candidate as T, dispatchReceiverValue = dispatchReceiverValue, candidate as T, dispatchReceiverValue = dispatchReceiverValue,
implicitExtensionReceiverValue = implicitExtensionReceiver, implicitExtensionReceiverValue = implicitExtensionReceiver
builtInExtensionFunctionReceiverValue = null
) )
} else { } else {
ProcessorAction.NEXT ProcessorAction.NEXT
@@ -247,8 +224,7 @@ class ScopeTowerLevel(
if (candidate.hasConsistentReceivers(extensionReceiver)) { if (candidate.hasConsistentReceivers(extensionReceiver)) {
processor.consumeCandidate( processor.consumeCandidate(
candidate as T, dispatchReceiverValue = candidate.dispatchReceiverValue(), candidate as T, dispatchReceiverValue = candidate.dispatchReceiverValue(),
implicitExtensionReceiverValue = implicitExtensionReceiver, implicitExtensionReceiverValue = implicitExtensionReceiver
builtInExtensionFunctionReceiverValue = null
) )
} else { } else {
ProcessorAction.NEXT ProcessorAction.NEXT
@@ -257,8 +233,7 @@ class ScopeTowerLevel(
TowerScopeLevel.Token.Objects -> scope.processClassifiersByName(name) { TowerScopeLevel.Token.Objects -> scope.processClassifiersByName(name) {
processor.consumeCandidate( processor.consumeCandidate(
it as T, dispatchReceiverValue = null, it as T, dispatchReceiverValue = null,
implicitExtensionReceiverValue = null, implicitExtensionReceiverValue = null
builtInExtensionFunctionReceiverValue = null
) )
} }
} }
@@ -26,7 +26,7 @@ fun <T> fooT2() : (t : T) -> T {
fun main(args : Array<String>) { fun main(args : Array<String>) {
args.foo()() args.foo()()
<!INAPPLICABLE_CANDIDATE!>args.foo1()()<!> <!INAPPLICABLE_CANDIDATE!>args.foo1()()<!>
<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>a<!>.foo1()() <!INAPPLICABLE_CANDIDATE!><!UNRESOLVED_REFERENCE!>a<!>.foo1()()<!>
<!UNRESOLVED_REFERENCE!>a<!>.foo1()(<!UNRESOLVED_REFERENCE!>a<!>) <!UNRESOLVED_REFERENCE!>a<!>.foo1()(<!UNRESOLVED_REFERENCE!>a<!>)
args.foo1()(1) args.foo1()(1)
@@ -59,7 +59,7 @@ fun test(a: A, b: B) {
b.(foo)() b.(foo)()
(b.foo)() <!INAPPLICABLE_CANDIDATE!>(b.foo)()<!>
foo(b) foo(b)
(foo)(b) (foo)(b)