[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");
|
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")
|
@TestMetadata("labelAndReceiverForInfix.kt")
|
||||||
public void testLabelAndReceiverForInfix() throws Exception {
|
public void testLabelAndReceiverForInfix() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/labelAndReceiverForInfix.kt");
|
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");
|
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")
|
@TestMetadata("labelAndReceiverForInfix.kt")
|
||||||
public void testLabelAndReceiverForInfix() throws Exception {
|
public void testLabelAndReceiverForInfix() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/labelAndReceiverForInfix.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/labelAndReceiverForInfix.kt");
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ class FirCallResolver(
|
|||||||
isPotentialQualifierPart = qualifiedAccess !is FirFunctionCall &&
|
isPotentialQualifierPart = qualifiedAccess !is FirFunctionCall &&
|
||||||
qualifiedAccess.explicitReceiver is FirResolvedQualifier &&
|
qualifiedAccess.explicitReceiver is FirResolvedQualifier &&
|
||||||
qualifiedResolver.isPotentialQualifierPartPosition(),
|
qualifiedResolver.isPotentialQualifierPartPosition(),
|
||||||
|
isImplicitInvoke = qualifiedAccess is FirImplicitInvokeCall,
|
||||||
typeArguments,
|
typeArguments,
|
||||||
session,
|
session,
|
||||||
components.file,
|
components.file,
|
||||||
@@ -300,6 +301,7 @@ class FirCallResolver(
|
|||||||
explicitReceiver = null,
|
explicitReceiver = null,
|
||||||
delegatedConstructorCall.argumentList,
|
delegatedConstructorCall.argumentList,
|
||||||
isPotentialQualifierPart = false,
|
isPotentialQualifierPart = false,
|
||||||
|
isImplicitInvoke = false,
|
||||||
typeArguments = typeArguments,
|
typeArguments = typeArguments,
|
||||||
session,
|
session,
|
||||||
components.file,
|
components.file,
|
||||||
@@ -347,6 +349,7 @@ class FirCallResolver(
|
|||||||
explicitReceiver = null,
|
explicitReceiver = null,
|
||||||
annotationCall.argumentList,
|
annotationCall.argumentList,
|
||||||
isPotentialQualifierPart = false,
|
isPotentialQualifierPart = false,
|
||||||
|
isImplicitInvoke = false,
|
||||||
typeArguments = emptyList(),
|
typeArguments = emptyList(),
|
||||||
session,
|
session,
|
||||||
components.file,
|
components.file,
|
||||||
@@ -449,6 +452,7 @@ class FirCallResolver(
|
|||||||
callableReferenceAccess.explicitReceiver,
|
callableReferenceAccess.explicitReceiver,
|
||||||
FirEmptyArgumentList,
|
FirEmptyArgumentList,
|
||||||
isPotentialQualifierPart = false,
|
isPotentialQualifierPart = false,
|
||||||
|
isImplicitInvoke = false,
|
||||||
emptyList(),
|
emptyList(),
|
||||||
session,
|
session,
|
||||||
components.file,
|
components.file,
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ data class CallInfo(
|
|||||||
val explicitReceiver: FirExpression?,
|
val explicitReceiver: FirExpression?,
|
||||||
val argumentList: FirArgumentList,
|
val argumentList: FirArgumentList,
|
||||||
val isPotentialQualifierPart: Boolean,
|
val isPotentialQualifierPart: Boolean,
|
||||||
|
val isImplicitInvoke: Boolean,
|
||||||
|
|
||||||
val typeArguments: List<FirTypeProjection>,
|
val typeArguments: List<FirTypeProjection>,
|
||||||
val session: FirSession,
|
val session: FirSession,
|
||||||
|
|||||||
+37
-9
@@ -184,15 +184,7 @@ internal class FirInvokeResolveTowerExtension(
|
|||||||
receiverGroup: TowerGroup
|
receiverGroup: TowerGroup
|
||||||
) {
|
) {
|
||||||
val invokeOnGivenReceiverCandidateFactory = CandidateFactory(context, invokeFunctionInfo)
|
val invokeOnGivenReceiverCandidateFactory = CandidateFactory(context, invokeFunctionInfo)
|
||||||
val task = InvokeFunctionResolveTask(
|
val task = createInvokeFunctionResolveTask(invokeFunctionInfo, receiverGroup, invokeOnGivenReceiverCandidateFactory)
|
||||||
components,
|
|
||||||
manager,
|
|
||||||
TowerDataElementsForName(invokeFunctionInfo.name, components.towerDataContext),
|
|
||||||
receiverGroup,
|
|
||||||
candidateFactoriesAndCollectors.resultCollector,
|
|
||||||
invokeOnGivenReceiverCandidateFactory,
|
|
||||||
candidateFactoriesAndCollectors.stubReceiverCandidateFactory
|
|
||||||
)
|
|
||||||
if (invokeBuiltinExtensionMode) {
|
if (invokeBuiltinExtensionMode) {
|
||||||
manager.enqueueResolverTask {
|
manager.enqueueResolverTask {
|
||||||
task.runResolverForBuiltinInvokeExtensionWithExplicitArgument(
|
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) {
|
if (receiver is FirQualifiedAccessExpression) {
|
||||||
val calleeReference = receiver.calleeReference
|
val calleeReference = receiver.calleeReference
|
||||||
if (calleeReference is FirSuperReference) {
|
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) }
|
manager.enqueueResolverTask { mainTask.runResolverForExpressionReceiver(info, receiver) }
|
||||||
invokeResolveTowerExtension.enqueueResolveTasksForExpressionReceiver(info, receiver)
|
invokeResolveTowerExtension.enqueueResolveTasksForExpressionReceiver(info, receiver)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -184,6 +184,7 @@ class FirSyntheticCallGenerator(
|
|||||||
explicitReceiver = null,
|
explicitReceiver = null,
|
||||||
argumentList = argumentList,
|
argumentList = argumentList,
|
||||||
isPotentialQualifierPart = false,
|
isPotentialQualifierPart = false,
|
||||||
|
isImplicitInvoke = false,
|
||||||
typeArguments = emptyList(),
|
typeArguments = emptyList(),
|
||||||
session = session,
|
session = session,
|
||||||
containingFile = components.file,
|
containingFile = components.file,
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ fun test(a: A) {
|
|||||||
<!INAPPLICABLE_CANDIDATE!>(a.x)()<!>
|
<!INAPPLICABLE_CANDIDATE!>(a.x)()<!>
|
||||||
if (a.x != null) {
|
if (a.x != null) {
|
||||||
a.<!INAPPLICABLE_CANDIDATE!>x<!>() // todo
|
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<!>()
|
||||||
a.(<!INAPPLICABLE_CANDIDATE!>foo<!>)()
|
a.(<!INAPPLICABLE_CANDIDATE!>foo<!>)()
|
||||||
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>(a.foo)()<!>
|
(a.foo)()
|
||||||
|
|
||||||
(a.foo)(this)
|
(a.foo)(this)
|
||||||
a.foo(this)
|
a.foo(this)
|
||||||
@@ -69,7 +69,7 @@ fun test(a: A, b: B) {
|
|||||||
a.<!INAPPLICABLE_CANDIDATE!>foo<!>()
|
a.<!INAPPLICABLE_CANDIDATE!>foo<!>()
|
||||||
a.(<!INAPPLICABLE_CANDIDATE!>foo<!>)()
|
a.(<!INAPPLICABLE_CANDIDATE!>foo<!>)()
|
||||||
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>(a.foo)()<!>
|
(a.foo)()
|
||||||
|
|
||||||
(a.foo)(this)
|
(a.foo)(this)
|
||||||
a.foo(this)
|
a.foo(this)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ fun test(a: A, b: B) {
|
|||||||
|
|
||||||
a.foo(this)
|
a.foo(this)
|
||||||
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>(a.foo)()<!>
|
(a.foo)()
|
||||||
|
|
||||||
(a.foo)(this)
|
(a.foo)(this)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -44,6 +44,7 @@ abstract class AbstractCandidateInfoProvider(
|
|||||||
containingDeclarations = emptyList(), // TODO - maybe we should pass declarations from context here (no visible differences atm)
|
containingDeclarations = emptyList(), // TODO - maybe we should pass declarations from context here (no visible differences atm)
|
||||||
containingFile = firFile,
|
containingFile = firFile,
|
||||||
isPotentialQualifierPart = false,
|
isPotentialQualifierPart = false,
|
||||||
|
isImplicitInvoke = false,
|
||||||
session = firSession,
|
session = firSession,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user