Transform variable-as-function calls for extension functions

In the following code example
  fun test(f: Any.() -> Unit) = 42.f()
front-end resolves variable-as-function call for 'f' as 'invoke'
with signature 'Function1<Any, Unit>#Any.() -> Unit'.
However, Function1<Any, Unit> has a single 'invoke' method
with signature 'Function1<Any, Unit>#(Any) -> Unit'.
This didn't cause any problems with loosely typed JVM and JS back-ends.
However, in IR with symbols this means a reference to non-existing
declaration.
This commit is contained in:
Dmitry Petrov
2017-05-03 11:26:43 +03:00
parent 7bd75df1f1
commit 1eb693b8ee
10 changed files with 219 additions and 14 deletions
@@ -12,6 +12,6 @@ FILE /extFunInvokeAsFun.kt
VALUE_PARAMETER value-parameter block: kotlin.Any?.() -> kotlin.Unit
BLOCK_BODY
RETURN type=kotlin.Nothing from='with2(Any?, Any?.() -> Unit): Unit'
CALL 'invoke() on Any?: Unit' type=kotlin.Unit origin=INVOKE
CALL 'invoke(Any?): Unit' type=kotlin.Unit origin=INVOKE
$this: GET_VAR 'value-parameter block: Any?.() -> Unit' type=kotlin.Any?.() -> kotlin.Unit origin=VARIABLE_AS_FUNCTION
$receiver: GET_VAR 'value-parameter receiver: Any?' type=kotlin.Any? origin=null
p1: GET_VAR 'value-parameter receiver: Any?' type=kotlin.Any? origin=null
@@ -0,0 +1,2 @@
fun test(receiver: Any?, fn: Any.(Int, String) -> Unit) =
receiver?.fn(42, "Hello")
@@ -0,0 +1,22 @@
FILE /extFunSafeInvoke.kt
FUN public fun test(receiver: kotlin.Any?, fn: kotlin.Any.(kotlin.Int, kotlin.String) -> kotlin.Unit): kotlin.Unit?
VALUE_PARAMETER value-parameter receiver: kotlin.Any?
VALUE_PARAMETER value-parameter fn: kotlin.Any.(kotlin.Int, kotlin.String) -> kotlin.Unit
BLOCK_BODY
RETURN type=kotlin.Nothing from='test(Any?, Any.(Int, String) -> Unit): Unit?'
BLOCK type=kotlin.Unit? origin=SAFE_CALL
VAR IR_TEMPORARY_VARIABLE val tmp0_safe_receiver: kotlin.Any?
GET_VAR 'value-parameter receiver: Any?' type=kotlin.Any? origin=null
WHEN type=kotlin.Unit? origin=SAFE_CALL
BRANCH
if: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'tmp0_safe_receiver: Any?' type=kotlin.Any? origin=null
arg1: CONST Null type=kotlin.Nothing? value='null'
then: CONST Null type=kotlin.Nothing? value='null'
BRANCH
if: CONST Boolean type=kotlin.Boolean value='true'
then: CALL 'invoke(Any, Int, String): Unit' type=kotlin.Unit origin=INVOKE
$this: GET_VAR 'value-parameter fn: Any.(Int, String) -> Unit' type=kotlin.Any.(kotlin.Int, kotlin.String) -> kotlin.Unit origin=VARIABLE_AS_FUNCTION
p1: GET_VAR 'tmp0_safe_receiver: Any?' type=kotlin.Any? origin=null
p2: CONST Int type=kotlin.Int value='42'
p3: CONST String type=kotlin.String value='Hello'
@@ -19,9 +19,9 @@ FILE /variableAsFunctionCall.kt
VALUE_PARAMETER value-parameter f: kotlin.String.() -> kotlin.Unit
BLOCK_BODY
RETURN type=kotlin.Nothing from='test2(String.() -> Unit): Unit'
CALL 'invoke() on String: Unit' type=kotlin.Unit origin=INVOKE
CALL 'invoke(String): Unit' type=kotlin.Unit origin=INVOKE
$this: GET_VAR 'value-parameter f: String.() -> Unit' type=kotlin.String.() -> kotlin.Unit origin=VARIABLE_AS_FUNCTION
$receiver: CONST String type=kotlin.String value='hello'
p1: CONST String type=kotlin.String value='hello'
FUN public fun test3(): kotlin.String
BLOCK_BODY
RETURN type=kotlin.Nothing from='test3(): String'