[FIR] Properly resolve implicit invoke calls

#KT-41990 Fixed
This commit is contained in:
Dmitriy Novozhilov
2020-09-18 16:39:14 +03:00
parent a8e81e9ad1
commit 896103b94b
13 changed files with 81 additions and 16 deletions
@@ -0,0 +1,8 @@
// ISSUE: KT-41990
fun getLambda(): String.() -> Unit = null!!
fun String.test_1(s: String) {
getLambda()()
getLambda()(s)
}
@@ -0,0 +1,8 @@
FILE: kt41990.kt
public final fun getLambda(): R|kotlin/String.() -> kotlin/Unit| {
^getLambda Null(null)!!
}
public final fun R|kotlin/String|.test_1(s: R|kotlin/String|): R|kotlin/Unit| {
R|/getLambda|().R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(this@R|/test_1|)
R|/getLambda|().R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(R|<local>/s|)
}
@@ -243,6 +243,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/analysis-tests/testData/resolve/javaStaticScopeInheritance.kt");
}
@TestMetadata("kt41990.kt")
public void testKt41990() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/kt41990.kt");
}
@TestMetadata("labelAndReceiverForInfix.kt")
public void testLabelAndReceiverForInfix() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/labelAndReceiverForInfix.kt");
@@ -243,6 +243,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/javaStaticScopeInheritance.kt");
}
@TestMetadata("kt41990.kt")
public void testKt41990() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/kt41990.kt");
}
@TestMetadata("labelAndReceiverForInfix.kt")
public void testLabelAndReceiverForInfix() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/labelAndReceiverForInfix.kt");
@@ -141,6 +141,7 @@ class FirCallResolver(
isPotentialQualifierPart = qualifiedAccess !is FirFunctionCall &&
qualifiedAccess.explicitReceiver is FirResolvedQualifier &&
qualifiedResolver.isPotentialQualifierPartPosition(),
isImplicitInvoke = qualifiedAccess is FirImplicitInvokeCall,
typeArguments,
session,
components.file,
@@ -300,6 +301,7 @@ class FirCallResolver(
explicitReceiver = null,
delegatedConstructorCall.argumentList,
isPotentialQualifierPart = false,
isImplicitInvoke = false,
typeArguments = typeArguments,
session,
components.file,
@@ -347,6 +349,7 @@ class FirCallResolver(
explicitReceiver = null,
annotationCall.argumentList,
isPotentialQualifierPart = false,
isImplicitInvoke = false,
typeArguments = emptyList(),
session,
components.file,
@@ -449,6 +452,7 @@ class FirCallResolver(
callableReferenceAccess.explicitReceiver,
FirEmptyArgumentList,
isPotentialQualifierPart = false,
isImplicitInvoke = false,
emptyList(),
session,
components.file,
@@ -38,6 +38,7 @@ data class CallInfo(
val explicitReceiver: FirExpression?,
val argumentList: FirArgumentList,
val isPotentialQualifierPart: Boolean,
val isImplicitInvoke: Boolean,
val typeArguments: List<FirTypeProjection>,
val session: FirSession,
@@ -184,15 +184,7 @@ internal class FirInvokeResolveTowerExtension(
receiverGroup: TowerGroup
) {
val invokeOnGivenReceiverCandidateFactory = CandidateFactory(context, invokeFunctionInfo)
val task = InvokeFunctionResolveTask(
components,
manager,
TowerDataElementsForName(invokeFunctionInfo.name, components.towerDataContext),
receiverGroup,
candidateFactoriesAndCollectors.resultCollector,
invokeOnGivenReceiverCandidateFactory,
candidateFactoriesAndCollectors.stubReceiverCandidateFactory
)
val task = createInvokeFunctionResolveTask(invokeFunctionInfo, receiverGroup, invokeOnGivenReceiverCandidateFactory)
if (invokeBuiltinExtensionMode) {
manager.enqueueResolverTask {
task.runResolverForBuiltinInvokeExtensionWithExplicitArgument(
@@ -219,6 +211,42 @@ internal class FirInvokeResolveTowerExtension(
}
}
fun enqueueResolveTasksForImplicitInvokeCall(info: CallInfo, receiverExpression: FirExpression) {
val explicitReceiverValue = ExpressionReceiverValue(receiverExpression)
val task = createInvokeFunctionResolveTask(info, TowerGroup.EmptyRoot)
manager.enqueueResolverTask {
task.runResolverForInvoke(
info, explicitReceiverValue,
TowerGroup.EmptyRoot
)
}
manager.enqueueResolverTask {
task.runResolverForBuiltinInvokeExtensionWithExplicitArgument(
info, explicitReceiverValue,
TowerGroup.EmptyRoot
)
}
manager.enqueueResolverTask {
task.runResolverForBuiltinInvokeExtensionWithImplicitArgument(
info, explicitReceiverValue,
TowerGroup.EmptyRoot
)
}
}
private fun createInvokeFunctionResolveTask(
info: CallInfo,
receiverGroup: TowerGroup,
candidateFactory: CandidateFactory = candidateFactoriesAndCollectors.candidateFactory
): InvokeFunctionResolveTask = InvokeFunctionResolveTask(
components,
manager,
TowerDataElementsForName(info.name, components.towerDataContext),
receiverGroup,
candidateFactoriesAndCollectors.resultCollector,
candidateFactory,
candidateFactoriesAndCollectors.stubReceiverCandidateFactory
)
}
@@ -66,10 +66,14 @@ class FirTowerResolver(
if (receiver is FirQualifiedAccessExpression) {
val calleeReference = receiver.calleeReference
if (calleeReference is FirSuperReference) {
return manager.enqueueResolverTask { mainTask.runResolverForSuperReceiver(info, receiver.typeRef) }
manager.enqueueResolverTask { mainTask.runResolverForSuperReceiver(info, receiver.typeRef) }
return
}
}
if (info.isImplicitInvoke) {
invokeResolveTowerExtension.enqueueResolveTasksForImplicitInvokeCall(info, receiver)
return
}
manager.enqueueResolverTask { mainTask.runResolverForExpressionReceiver(info, receiver) }
invokeResolveTowerExtension.enqueueResolveTasksForExpressionReceiver(info, receiver)
}
@@ -184,6 +184,7 @@ class FirSyntheticCallGenerator(
explicitReceiver = null,
argumentList = argumentList,
isPotentialQualifierPart = false,
isImplicitInvoke = false,
typeArguments = emptyList(),
session = session,
containingFile = components.file,
@@ -15,7 +15,7 @@ fun test(a: A) {
<!INAPPLICABLE_CANDIDATE!>(a.x)()<!>
if (a.x != null) {
a.<!INAPPLICABLE_CANDIDATE!>x<!>() // todo
<!INAPPLICABLE_CANDIDATE!>(a.x)()<!>
(a.x)()
}
}
}
@@ -27,7 +27,7 @@ fun test(a: A, b: B) {
a.<!INAPPLICABLE_CANDIDATE!>foo<!>()
a.(<!INAPPLICABLE_CANDIDATE!>foo<!>)()
<!INAPPLICABLE_CANDIDATE!>(a.foo)()<!>
(a.foo)()
(a.foo)(this)
a.foo(this)
@@ -69,7 +69,7 @@ fun test(a: A, b: B) {
a.<!INAPPLICABLE_CANDIDATE!>foo<!>()
a.(<!INAPPLICABLE_CANDIDATE!>foo<!>)()
<!INAPPLICABLE_CANDIDATE!>(a.foo)()<!>
(a.foo)()
(a.foo)(this)
a.foo(this)
@@ -10,7 +10,7 @@ fun test(a: A, b: B) {
a.foo(this)
<!INAPPLICABLE_CANDIDATE!>(a.foo)()<!>
(a.foo)()
(a.foo)(this)
}
@@ -44,6 +44,7 @@ abstract class AbstractCandidateInfoProvider(
containingDeclarations = emptyList(), // TODO - maybe we should pass declarations from context here (no visible differences atm)
containingFile = firFile,
isPotentialQualifierPart = false,
isImplicitInvoke = false,
session = firSession,
)
}
@@ -85,4 +86,4 @@ class CheckExtensionForCompletionCandidateInfoProvider(
val candidateHasExtensionReceiver = callableSymbol.fir.receiverTypeRef != null
callHasExtensionReceiver != candidateHasExtensionReceiver
}
}
}