Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How resolving Kotlin functions/properties with the same name work?

The following statement compiles and prints "fun: called":

fun main(vararg args: String) {
    fun toCall(arg: String) = println("fun: $arg")
    val toCall = fun(arg: String) = println("val: $arg")
    toCall("called")
}

Note: the same problem would arise if they were top level declarations or inside a class, this is just the simplest repro with local function/variable.

Looking for clarification on why this compiles in the first place?
What rule comes into play that picks the function over the property?

Note: it's possible to call the val one through:

  • (toCall)("called")
  • toCall.invoke("called")
like image 515
TWiStErRob Avatar asked Nov 07 '22 03:11

TWiStErRob


1 Answers

This document regarding name resolution contains details about it.

I will just quote some passages out of it specifically dealing with your problem. It contains several other interesting things as well, but I think I would end up copying everything here then ;-) If you are interested, I can only recommend you to read it completely.

Summarizing, the compiler divides the functions (member/extension/member extension)/properties into groups and decides which one to call first... The properties are put in the group of the invoke-functions and in the following passage you already see why the function was taken before your val:

The property is considered together with the invoke function. Groups of properties with invoke functions are mixed with groups of regular functions, in a sense that a group of properties can have higher priority than a group of functions and vice versa. However, functions and properties can’t go in one group: the function always surpasses the property of the same category. Both the property and the invoke function determine the priority of the group: we compare the priority of the property and of the invoke function and the "lowest" one becomes the group priority.

That's why the function was considered first here and the property later. As soon as you specified invoke it was clear that it can only be the property as the function itself has no visible invoke (lets not go down the byte code now ;-)). Now (toCall) behaves similarly. Here it is clear, that toCall can only be the property. It isn't possible to call (toCall) with the function (compile errors: function invocation expected / the function invoke is not found).

The linked document also contains a sample with a member property function followed by this statement, which basically also confirms the previous regarding local functions:

Note that there is no member function named foo, but if it was present, it would be put into a separate group with the highest priority.

like image 89
Roland Avatar answered Nov 14 '22 21:11

Roland