[FIR] Properly resolve implicit invoke calls
#KT-41990 Fixed
This commit is contained in:
@@ -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|)
|
||||
}
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
+5
@@ -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,
|
||||
|
||||
+37
-9
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
+6
-2
@@ -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)
|
||||
}
|
||||
|
||||
+1
@@ -184,6 +184,7 @@ class FirSyntheticCallGenerator(
|
||||
explicitReceiver = null,
|
||||
argumentList = argumentList,
|
||||
isPotentialQualifierPart = false,
|
||||
isImplicitInvoke = false,
|
||||
typeArguments = emptyList(),
|
||||
session = session,
|
||||
containingFile = components.file,
|
||||
|
||||
+1
-1
@@ -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)()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -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)
|
||||
}
|
||||
|
||||
+2
-1
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user