[FIR] Fix FP UNRESOLVED_REFERENCE on implicit invoke() after a safe call

`invoke()` function of functional types is always defined
in such a way that its explicit receiver comes as the first
value parameter. Extension-function types contain the very
same `invoke` function, they just additionally have the
`@ExtensionFunctionType` annotation.

In the related test there is such an `invoke` function and
in the presented call its explicit receiver is the anonymous
function `fun Int.() = 1` itself. So the safe-checked `1`

^KT-60056
This commit is contained in:
Nikolay Lunyak
2023-11-22 14:16:03 +02:00
committed by Space Team
parent 502b422b6b
commit e4781d8508
2 changed files with 14 additions and 3 deletions
@@ -612,8 +612,19 @@ fun FirQualifiedAccessExpression.createSafeCall(receiver: FirExpression, source:
}
this.source = receiver.source?.fakeElement(KtFakeSourceElementKind.CheckedSafeCallSubject)
}
replaceExplicitReceiver(checkedSafeCallSubject)
// If an `invoke` function from a functional type expects a
// receiver, it's still defined as the first value parameter.
// A construction like `1.(fun Int.() = 1)()` means we're calling
// `Function1<Int, Unit>.invoke(Int)`.
if (this is FirImplicitInvokeCall) {
val newArguments = buildArgumentList {
arguments.add(checkedSafeCallSubject)
arguments.addAll(this@createSafeCall.arguments)
}
replaceArgumentList(newArguments)
} else {
replaceExplicitReceiver(checkedSafeCallSubject)
}
return buildSafeCallExpression {
this.receiver = receiver
@OptIn(FirContractViolation::class)
@@ -81,6 +81,6 @@ fun test() {
val i : Int? = null
i.<!UNSAFE_IMPLICIT_INVOKE_CALL!>(fun Int.() = 1)<!>();
<!INAPPLICABLE_CANDIDATE!>{}<!><Int>()
1<!UNNECESSARY_SAFE_CALL!>?.<!>(<!UNRESOLVED_REFERENCE!>fun Int.() = 1<!>)()
1<!UNNECESSARY_SAFE_CALL!>?.<!>(fun Int.() = 1)()
1.<!NO_RECEIVER_ALLOWED!>{}<!>()
}