[FIR] Properly set isReceiver for implicit invoke on function types

This commit is contained in:
Nikolay Lunyak
2023-11-28 12:01:34 +02:00
committed by Space Team
parent 2bd77d5cdc
commit c69c34ff8b
11 changed files with 21 additions and 45 deletions
@@ -471,12 +471,17 @@ internal object CheckArguments : CheckerStage() {
candidate.symbol.lazyResolveToPhase(FirResolvePhase.STATUS) candidate.symbol.lazyResolveToPhase(FirResolvePhase.STATUS)
val argumentMapping = val argumentMapping =
candidate.argumentMapping ?: error("Argument should be already mapped while checking arguments!") candidate.argumentMapping ?: error("Argument should be already mapped while checking arguments!")
for (argument in callInfo.arguments) {
val isInvokeFromExtensionFunctionType = candidate.explicitReceiverKind == DISPATCH_RECEIVER
&& candidate.dispatchReceiver?.resolvedType?.isExtensionFunctionType == true
&& (candidate.symbol as? FirNamedFunctionSymbol)?.name == OperatorNameConventions.INVOKE
for ((index, argument) in callInfo.arguments.withIndex()) {
candidate.resolveArgument( candidate.resolveArgument(
callInfo, callInfo,
argument, argument,
argumentMapping[argument], argumentMapping[argument],
isReceiver = false, isReceiver = index == 0 && isInvokeFromExtensionFunctionType,
sink = sink, sink = sink,
context = context context = context
) )
@@ -2,6 +2,6 @@ fun bar(doIt: Int.() -> Int) {
1.doIt() 1.doIt()
1<!UNNECESSARY_SAFE_CALL!>?.<!>doIt() 1<!UNNECESSARY_SAFE_CALL!>?.<!>doIt()
val i: Int? = 1 val i: Int? = 1
<!ARGUMENT_TYPE_MISMATCH!>i<!>.doIt() i.<!UNSAFE_IMPLICIT_INVOKE_CALL!>doIt<!>()
i?.doIt() i?.doIt()
} }
@@ -77,9 +77,9 @@ fun main1() {
fun test() { fun test() {
{x : Int -> 1}<!NO_VALUE_FOR_PARAMETER!>()<!>; {x : Int -> 1}<!NO_VALUE_FOR_PARAMETER!>()<!>;
(fun Int.() = 1)<!NO_VALUE_FOR_PARAMETER!>()<!> (fun Int.() = 1)<!NO_VALUE_FOR_PARAMETER!>()<!>
<!ARGUMENT_TYPE_MISMATCH!>"sd"<!>.(fun Int.() = 1)() "sd".<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>(fun Int.() = 1)<!>()
val i : Int? = null val i : Int? = null
<!ARGUMENT_TYPE_MISMATCH!>i<!>.(fun Int.() = 1)(); i.<!UNSAFE_IMPLICIT_INVOKE_CALL!>(fun Int.() = 1)<!>();
<!INAPPLICABLE_CANDIDATE!>{}<!><Int>() <!INAPPLICABLE_CANDIDATE!>{}<!><Int>()
1<!UNNECESSARY_SAFE_CALL!>?.<!>(<!UNRESOLVED_REFERENCE!>fun Int.() = 1<!>)() 1<!UNNECESSARY_SAFE_CALL!>?.<!>(<!UNRESOLVED_REFERENCE!>fun Int.() = 1<!>)()
1.<!NO_RECEIVER_ALLOWED!>{}<!>() 1.<!NO_RECEIVER_ALLOWED!>{}<!>()
@@ -34,7 +34,7 @@ fun test4() {
// should be an error on receiver, shouldn't be thrown away // should be an error on receiver, shouldn't be thrown away
fun test5() { fun test5() {
<!ARGUMENT_TYPE_MISMATCH!>1<!>.(fun String.()=1)() 1.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>(fun String.()=1)<!>()
} }
fun <R: Any> R?.sure() : R = this!! fun <R: Any> R?.sure() : R = this!!
@@ -12,7 +12,7 @@ fun test(f: Runnable.(Int) -> Unit, runnable: Runnable) {
fun Int.test(f: String.(Int) -> Unit) { fun Int.test(f: String.(Int) -> Unit) {
f("", 0) f("", 0)
<!ARGUMENT_TYPE_MISMATCH!>f<!>(<!ARGUMENT_TYPE_MISMATCH!>""<!>) f(<!NO_VALUE_FOR_PARAMETER!>"")<!>
with("") { with("") {
f(0) f(0)
f(<!ARGUMENT_TYPE_MISMATCH!>0.0<!>) f(<!ARGUMENT_TYPE_MISMATCH!>0.0<!>)
@@ -1,30 +0,0 @@
// KT-5362 Compiler crashes on access to extension method from nested class
class Outer {
class Nested{
fun foo(s: String) = s.<!UNRESOLVED_REFERENCE!>extension<!>()
}
private fun String.extension(): String = this
}
// EA-64302 - UOE: CodegenContext.getOuterExpression
fun Activity.toast() = Unit
class Activity(){
class Fragment{
fun call() = <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>toast<!>()
}
}
// KT-8814 No error in IDE for invalid invoke of OuterClass.()->Unit in static nested class
public class Manager {
fun task(callback: Manager.() -> Unit): Task {
val task = Task(callback)
return task
}
class Task(val callback: Manager.() -> Unit) : Runnable {
override public fun run() {
<!ARGUMENT_TYPE_MISMATCH!>callback<!>() // Manager is not accessible here, but no error is shown
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// KT-5362 Compiler crashes on access to extension method from nested class // KT-5362 Compiler crashes on access to extension method from nested class
class Outer { class Outer {
class Nested{ class Nested{
@@ -1,16 +1,16 @@
fun test1() { fun test1() {
<!ARGUMENT_TYPE_MISMATCH!>1<!>. (fun String.(i: Int) = i )(1) 1. <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>(fun String.(i: Int) = i )<!>(1)
<!ARGUMENT_TYPE_MISMATCH!>1<!>.(label@ fun String.(i: Int) = i )(1) 1.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>(label@ fun String.(i: Int) = i )<!>(1)
} }
fun test2(f: String.(Int) -> Unit) { fun test2(f: String.(Int) -> Unit) {
<!ARGUMENT_TYPE_MISMATCH!>11<!>.(f)(1) 11.(<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>f<!>)(1)
<!ARGUMENT_TYPE_MISMATCH!>11<!>.(f)<!NO_VALUE_FOR_PARAMETER!>()<!> 11.(f)<!NO_VALUE_FOR_PARAMETER!>()<!>
} }
fun test3() { fun test3() {
fun foo(): String.(Int) -> Unit = {} fun foo(): String.(Int) -> Unit = {}
<!ARGUMENT_TYPE_MISMATCH!>1<!>.(foo())(1) 1.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>(foo())<!>(1)
} }
@@ -9,5 +9,5 @@ fun test(identifier: SomeClass, fn: String.() -> Unit) {
<!NONE_APPLICABLE!>identifier<!>() <!NONE_APPLICABLE!>identifier<!>()
<!NONE_APPLICABLE!>identifier<!>(123) <!NONE_APPLICABLE!>identifier<!>(123)
<!OPERATOR_MODIFIER_REQUIRED!>identifier<!>(<!ARGUMENT_TYPE_MISMATCH!>1<!>, <!TOO_MANY_ARGUMENTS!>2<!>) <!OPERATOR_MODIFIER_REQUIRED!>identifier<!>(<!ARGUMENT_TYPE_MISMATCH!>1<!>, <!TOO_MANY_ARGUMENTS!>2<!>)
<!ARGUMENT_TYPE_MISMATCH!>1<!>.fn() 1.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>fn<!>()
} }
@@ -16,7 +16,7 @@ fun test(a: A, b: B) {
b.(foo)() b.(foo)()
<!ARGUMENT_TYPE_MISMATCH!>(b.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>foo<!>)()<!> (b.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>foo<!>)<!NO_VALUE_FOR_PARAMETER!>()<!>
foo(b) foo(b)
(foo)(b) (foo)(b)
@@ -8,5 +8,5 @@ fun test(identifier: SomeClass, fn: String.() -> Unit) {
<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>identifier<!>() <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>identifier<!>()
<!OPERATOR_MODIFIER_REQUIRED!>identifier<!>(<!TOO_MANY_ARGUMENTS!>123<!>) <!OPERATOR_MODIFIER_REQUIRED!>identifier<!>(<!TOO_MANY_ARGUMENTS!>123<!>)
<!OPERATOR_MODIFIER_REQUIRED!>identifier<!>(<!TOO_MANY_ARGUMENTS!>1<!>, <!TOO_MANY_ARGUMENTS!>2<!>) <!OPERATOR_MODIFIER_REQUIRED!>identifier<!>(<!TOO_MANY_ARGUMENTS!>1<!>, <!TOO_MANY_ARGUMENTS!>2<!>)
<!ARGUMENT_TYPE_MISMATCH!>1<!>.fn() 1.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>fn<!>()
} }