blob: de796dc26ca4dba48ef59f870df1a5a59d74e229 [file] [log] [blame]
== Kotlin name resolution
This article describes the process of overload resolution in the Kotlin programming language.
It explains how the compiler chooses the function that should be called in each invocation.
For example, if you write `a.foo(b)` somewhere in your code, the compiler has to find the most appropriate function named `foo` in the context.
This task is extremely easy if there is only one function with the given name.
However, Kotlin allows you to overload functions: define several functions with the same name but different argument lists.
In this case the task of choosing the best one might be rather tricky.
What's more these functions may come from different sources: it may be a regular top-level function, a member of a class, an extension function, a local declaration (defined inside another function); it may be declared in the same package or imported, and so on.
It might be even a variable of a function type.
All these cases may complicate things, and the goal of this document is to clarify how the resolution process works.
=== Implicit and Explicit receivers
This section introduces basic concepts that will be used later.
It describes explicit and implicit receivers and shows where the latter come from.
Consider a regular top-level non-extension function:
[source,kotlin]
----
fun foo(i: Int) { ... }
----
Such function is called simply by its name, without specifying any receiver (it just doesn't have one):
[source,kotlin]
----
foo(42)
----
This is the most simple case.
If the function is a member or an extension, it can be called by specifying its receiver explicitly.
In this case we say that this function is called via an _explicit receiver_:
[source,kotlin]
----
class A {
fun foo(s: String) { ... }
}
>>> a.foo("x") <1>
----
<1> The function `foo` is called with the explicit receiver `a`
An explicit receiver is a receiver that is written directly.
In the example above `a` is the explicit receiver for the function call `foo("x")`.
Note that a function invoked with the explicit receiver `a` doesn't have to be a member of the class `A`, it might be an extension to it as well (or to a supertype of `A`).
The same function might be called without an explicit receiver if a proper `this` reference is available in the context.
For example, inside an extension function to the `A` class, we can call `foo` without specifying `this` explicitly:
[source,kotlin]
----
fun A.bar() {
this.foo("y") <1>
foo("z") <2>
}
----
<1> `this` is an explicit receiver
<2> `this` is an implicit receiver
In the latter case when we omit `this` we say that the function `foo` is called via an _implicit receiver_.
We've just bumped into the first challenge the Kotlin compiler has to cope with: when it sees a simple function invocation `foo()` it doesn't mean that `foo` is a top-level function.
It might also be a member or extension function called via an implicit receiver.
Let's look at more examples of code with implicit receivers.
Inside a class, you use `this` to access an instance of the class, and you can call members or extensions just by their names:
[source,kotlin]
----
class A {
fun foo() {}
fun f() {
foo() <1>
}
}
----
<1> This member function is called via implicit receiver `this`
If the class has a _companion object_, you may call members of the companion object by names as well:
[source,kotlin]
----
class A {
fun g() {
A.bar() <1>
bar() <2>
}
companion object {
fun bar() {}
}
}
----
<1> You may call the function from the companion object by the class name
<2> Or you can omit the explicit specification
In this case the class name `A`, the reference to its companion object, becomes an implicit receiver available in this context.
That means that it's convenient but not correct to think of an implicit receiver only as an available `this`: the companion object might be an implicit receiver as well.
Another common case with implicit receivers is _lambdas with receiver_.
For example, the function `with` below takes such a lambda as a second argument:
[source,kotlin]
----
fun f() {
with("str") {
toUpperCase() <1>
}
}
----
<1> Implicit receiver is `this@with`
Inside the lambda you normally call functions on `this` receiver without specifying it, so it becomes implicit.
We saw examples with different implicit receivers in the context.
Note that inside a block of code (lambda, or function body) several implicit receivers might be available.
And that's a very frequent case.
Imagine that the function from the example above is a member of the class (we name it `g` now):
[source,kotlin]
----
class B {
fun g(...) {
with("str") {
/* ... */ <1>
}
}
}
----
<1> Two receivers `this@with` and `this@B` are available
In this case you can call methods on either of the implicit receivers `this@with` and `this@B`.
Making this function an extension and adding a companion object increases the number of implicit receivers even more.
These implicit receivers are actually ordered: the one that is closer goes first.
For example, `this@with` goes before `this@B`.
An implicit receiver corresponding to a class goes before the receiver corresponding to its companion object.
Note that several companion objects might become implicit receivers, for example if the class extends another class with a companion object:
[source,kotlin]
----
class A {
companion object { ... }
}
class B: A() {
fun h() { ... } (1)
companion object { ... }
}
----
<1> Implicit receivers: this@B, B (companion object to the class B), A (companion object to the class A)
In the further discussion we'll rely a lot on the concept of implicit receivers available in any given context.
As a summary, you may think of them as a list of all available `this` references together with references to companion objects, e.g. `[this@with, this@B, B]`.
=== Name resolution for a call with an explicit receiver
This section describes how the Kotlin compiler resolves a call when an explicit receiver is present.
Let's consider the call `a.foo()` where the explicit receiver `a` has a type `A`.
The function `foo` can be:
- a member of the class `A`;
- an extension function to `A`;
- a member extension function.
[NOTE]
.A member extension function
====
You can see an example of a member extension function call below:
[source,kotlin]
----
interface Builder {
operator fun String.unaryPlus()
}
fun Builder.addABC() {
"ABC".unaryPlus() <1>
+ "ABC" <2>
}
----
<1> this call is resolved to a member extension `unaryPlus`
<2> the same call using the convention for the `+` sign
The `unaryPlus` function is a member extension: it's an extension to `String` and a member of the class `Builder` at the same time.
Such functions can be called only if both receivers are present in the context: in the example above `"ABC"` is an explicit receiver and `this` (referring to `Builder`) is an implicit one.
Note that only an extension receiver (`String` in this example) may be explicit.
The reference to `Builder` will always be an implicit receiver.
====
For now, we suppose that `foo` in the call `a.foo()` is a regular function and not a variable of a function type.
The latter case will be covered in the section "Name resolution for the `invoke` convention".
Several `foo` functions might be available in the context: members, extensions and member extensions.
As the Kotlin language supports function overloading, each of these categories can contain many functions with the same name.
The task of the compiler is to choose the most appropriate function (or to report ambiguity if there're many of them).
Functions from different categories have different priorities, e.g. a member always wins over an extension.
If a member can be called, you can't force the compiler to choose an extension:
[source,kotlin]
----
operator fun String.plus(s: String) = "!" <1>
class String {
operator fun plus(other: Any?): String <2>
}
>>> "a" + "b" <3>
----
<1> this extension method will never be called
<2> because a member always wins
<3> the member is chosen, not the extension function
Even though the extension function is more precise for the call (it takes `String` as a parameter, while the member takes `Any?`), it's never chosen.
If it was, it would be too easy to break existing code without noticing that by adding an extension.
You see now that members go before extensions, but what about member extensions?
They have higher priority compared to top-level extensions, but lower than local extensions.
Below we'll cover the details.
[NOTE]
.Local Declarations always Win
====
We call a variable or function local if it's declared inside a function.
In Kotlin you can declare functions inside other functions; it helps greatly to organize the code and to extract duplicated fragments without verbosity.
You can even declare an extension function locally, it's useful if such an extension makes code more readable and only makes sense inside another function.
To make the resolution rules clear, we stick to the rule "local declaration wins".
That doesn't mean that a local extension function might be prioritized over a member, but it has higher priority than all other extension functions (including member extensions).
====
Now let's discuss the specific steps the compiler performs to resolve a call:
* First the Kotlin compiler collects all possibly applicable functions in ordered groups.
Members is an example of such a group - the one with the highest priority.
* Then for each group the most specific function is chosen; if many are applicable and no one is the most specific, then an `ambiguity` error is reported.
We omit the description of the process of choosing the most specific function.
It works very similar to how the most specific method is found in Java and in simple cases is rather straightforward.
Note that if any function from an earlier group is applicable, it's chosen, in spite of the fact that the next group may contain a more precise function.
This was shown in the example with members and extensions above: a member function is chosen, although an extension is available that is more precise.
Below we describe the groups of functions that are created to resolve `a.foo()`:
1. _Members of `a`._
All overloaded member functions with the name `foo` have the same priority and go in one group.
2. _Local extension functions._
Several groups of local extensions are created.
The functions are prioritized by scopes: more local functions have higher priority and go earlier.
Two overloaded functions from the same scope will be in the same group.
Note that local extensions have higher priority than other extensions, however, even they can't go before members.
3. _Member extensions_.
Let's say several implicit receivers are available in the context.
Each of them adds a group of member extensions named `foo`: extensions that are declared as members of a class corresponding to the receiver.
Such groups are prioritized by their implicit receivers.
The closest receiver goes first (see "Implicit and Explicit receivers" for the details of implicit receivers order).
4. _Top-level extension functions_.
All other extension functions are declared at the package level.
They can be either declared in the same package as the resolved call or imported (directly or via star-import).
Several groups of functions are created here, their order will be described in the note "Top-level scope chain" below.
Let's consider the following artificial example to see the groups of functions that are created to resolve the call `a.foo()`:
[source,kotlin]
----
class A
class B { fun A.foo() = 2 }
class C { fun A.foo() = 3 }
fun A.foo() = 4
fun C.test(a: A) {
fun A.foo() = 1
with (B()) {
fun A.foo() = 0
a.foo() <1>
}
}
----
<1> a call to resolve
Five functions with the name `foo` are available in the context: two local extensions, two member extensions and a top-level extension.
Five groups of functions are created, each group contains one function.
The value the function returns reveals an order of its group: the function #0 (a function that returns 0) has the highest priority and goes first.
In this example it is simple to see which function is called: the closest local function #0.
But the example illustrates well the different groups of functions:
1. _Members._
The class `A` has no members named `foo`, so no groups are created.
2. _Local extensions._
Two local extension functions are declared: #0 and #1.
They are declared in different scopes, so two groups are created.
The group containing the function #0 (the closest one) has higher priority.
3. _Member extensions_.
Two implicit receivers are available.
The first one of type `B` is a receiver in a lambda with receiver (lambda is the argument of the `with` function).
The second one of type `C` is an extension receiver of the function `test`.
Each receiver adds the corresponding group (a group containing function #2 goes first, then a group with function #3).
Note that if several overloaded member extensions `foo` were declared in the class `B`, they would all go in one group.
4. _Top-level extensions_.
One group containing an extension function #4 is created.
Note that all local functions go before all member extensions, so the function #1 has higher priority than the function #2, although one might think that second one is closer.
Here you can see the Kotlin rule "local declarations win" in action.
We can slightly modify the example above to see when the function not from the first group is chosen:
[source,kotlin]
----
class A
class B { fun A.foo(i: Int) = 0 }
class C { fun A.foo(a: Any) = 1 }
fun A.foo(i: Int?) = 2
fun C.test(a: A) {
with (B()) {
a.foo("abc") // the function #1 is called
val i: Int? = ...
a.foo(i) // the function #2 is called
}
}
----
We removed local functions and added different parameters to remaining functions `foo`.
For each of the calls `a.foo("abc")` and `a.foo(i)` three groups of functions are created.
The function from the first group #0 is inapplicable in both cases, so the Kotlin compiler tries to find the first applicable function from the next groups.
It's function #1 for `String` argument and #2 for nullable argument (both functions #0 and #1 expect a non-null parameter).
[NOTE]
.Top-level scope chain
====
In Kotlin you can declare a function at the top-level.
Such a function might be declared at the same package as the usage or imported (explicitly or via star-import).
Top-level functions are prioritized in the following order:
1. _Explicit imports_.
If you import the necessary function by name, it has the highest priority.
2. _Functions in the same package_.
Such function may be located in the same file as the usage or in the other files in the same package.
3. _Star-imports_.
By using `*` you import all contents of a package.
Note that the functions imported in this way have lower priority then the functions imported directly.
4. _Functions from stdlib_.
The Kotlin standard library contains lots of extension functions.
They are all implicitly imported in any Kotlin file.
If you declare the function with the same name as in stdlib, then use it from the same package or import it, your function will have higher priority then the library function.
Note that explicit import has the highest priority.
That means it might be unsafe to replace an explicit import with star import, because the resolution for the call of imported function might change.
If a function with the same name is declared in the same package and is applicable, it might be chosen instead of the function that was explicitly imported.
The action "Optimize imports" in IntelliJ IDEA does everything correctly, so prefer using it.
In the example below the function `foo` from another package `a` is chosen because it is imported explicitly.
The function `foo` from the same package has lower priority:
[source,kotlin]
----
// first file
package a
class A
fun A.foo() = 1
// second file
package b
import a.A
import a.foo
fun A.foo() = 2
fun test(a: A) {
a.foo() <1>
}
----
<1> the function #1 is called
However, if you replace the import directives with `import a.*`, the function `foo` declared in the package `b` will be chosen.
====
Now let's discuss a case when the receiver is not present: it's either absent or implicit.
=== Name resolution for a call without an explicit receiver
Let's consider the call `foo()`.
Depending on the context, it might be a call on an implicit receiver like in `this.foo()` or just calling a regular function that is neither a member nor an extension.
This case is resolved similarly to the case when an explicit receiver is present.
The Kotlin compiler constructs ordered groups of functions, then tests the applicability of the functions from each group.
If an applicable function is found, it's the result.
We create the following groups of functions to resolve the call `foo()`:
1. _Local functions_.
All local non-extension functions named `foo` are added here.
We put them in several groups according to the scopes they are declared in.
More local function wins, as before.
2. _Functions for each implicit receiver as if it was explicit_.
The previous section describes how to construct groups of functions for the case when explicit receiver is present.
We repeat this process for each implicit receiver available in the context.
In a sense, we try to resolve the call `foo()` like `this.foo()` where `this` is an implicit receiver.
If two implicit receivers are available, all the functions for the first receiver go before all the functions for the second one.
Let's say `this@a` and `this@b` are implicit receivers, and `this@a` is closer in the scope and goes first.
At first we add groups of members, local extensions, member extensions, top-level extensions (as was described before) constructed for the call `this@a.foo()`, then we repeat the whole process for the call `this@b.foo()`.
Note that in this case an extension to `this@a` may be preferred to a member of `this@b`: the order of implicit receivers is more important.
3. _Top-level functions_.
All other non-extension functions constitute several groups in an order described in the note "Top-level scope chain" above.
Let's look at an example:
[source,kotlin]
----
class A
fun A.foo() = 1
class B { fun foo() = 2 }
fun foo() = 3
fun B.test(a: A) {
fun foo() = 0
with(a) {
foo()
}
}
----
The Kotlin compiler constructs the following groups:
1. Local functions.
The local function returning 0 (the function #0) is declared, and the first group contains only this function.
Note that the function #0 is applicable, so it will be the result.
2. The groups of functions built for the first implicit receiver `this@with` of the type `A`.
We perform the whole process of building the groups of functions for the call `this@with.foo()` as if the implicit receiver was written explicitly.
Only an extension function for `A` exists (the function #1), so it goes next.
3. The functions for the second implicit receiver `this@test` of the type `B`.
The class `B` has a member named `foo` (the function #2), so this member composes the next group.
Note that if both a member and an extension for the class `B` were available, the member would go in a separate group with higher priority, exactly like for the call `this@test.foo()`.
4. Top-level functions with the name `foo`.
The function #3 goes at last here after the functions for the implicit receivers.
We described how the Kotlin compiler prioritizes the functions for resolving a call without an explicit receiver.
_The order of implicit receivers is important._
Note how in the following example after you swap two arguments of `with` functions, another method is called:
[source,kotlin]
----
class A { fun foo() = 1 }
class B { fun foo() = 2 }
fun test(a: A, b: B) {
with (b) { with (a) { foo() } }
with (a) { with (b) { foo() } }
}
----
These `foo` calls look very similar, they differ only in the order of implicit receivers available in the context.
However, different functions are called: function #1 in the first case and function #2 in the second one.
Two implicit receivers are available for each `foo` invocation: for simplicity let's say `a` and `b`; in the code we may reference the closest one by `this@with`.
In the first case `a` is closer and has more priority than `b`, so a member of `A` is called (function #1).
In the second case it's a member of `B` (function #2).
[NOTE]
.Static functions from Java code
====
A static function `foo` declared in a Java class `A` can be called simply as `foo()` in any Kotlin class that extends `A` (directly or indirectly).
Static functions are handled in a special way, because they don't correspond to any implicit receiver.
However, they have exactly the same treatment as if they had been written in Kotlin and declared in the `companion object` to `A`.
This Java class `A` contains a static function `foo`:
[source,java]
----
public class A {
public static int foo() {
return 0;
}
}
----
If you declared the same class in Kotlin, you might have put the function `foo` in the companion object:
[source,kotlin]
----
open class A1 {
companion object { fun foo() = 0 }
}
----
You may extend the class declared in Java in the Kotlin code:
[source,kotlin]
----
class C {
inner class B : A() {
init { foo() }
}
fun foo() = 1
}
----
The list of implicit receivers for the context in which `foo()` is called will be:
* `this@B`,
* `A` (the `companion object` for `A` if it's declared in Kotlin),
* `this@C`.
If `A` is declared in Java, there's no implicit receiver corresponding to its companion object, because there is no companion object.
However, all static Java methods are added with the same order as if they were members of the `companion object`: they go right after the members of the class.
====
=== Name resolution for the `invoke` convention
This section describes how hidden `invoke` calls are resolved.
First we'll describe the `invoke` convention, and then go into details of the name resolution process.
This convention in Kotlin lets you call a value as a function if it has the appropriate `invoke` method, which can be a member or an extension:
[source,kotlin]
----
interface MyFunction {
operator fun invoke(s: String): Int
}
fun test(f: MyFunction) {
val i: Int = f("a") <1>
}
----
<1> the call `f.invoke("a")` by convention is simplified to `f("a")`
The `invoke` function should be applicable on the arguments passed.
When you call a value of function type as a regular function in Kotlin, the same convention takes place.
The function type `(Int) -> Int` is syntactic sugar for `Function1<Int, Int>`, which is a regular interface declared in the standard library:
[source,kotlin]
----
interface Function1<in P1, out R> : Function<R> {
operator fun invoke(p1: P1): R
}
>>> val f: (Int) -> Int = { it + 1 }
>>> f(11) <1>
----
<1> the short form of the call `f.invoke(11)`
If a value has extension function type, it can be called as extension function:
[source,kotlin]
----
>>> val f : Int.() -> Int = { this }
>>> 1.f()
----
The resolution of such call works through the `invoke` convention as well, but in this case the receiver becomes the first argument of the `invoke` function.
That means the call `1.f()` might be rewritten as `f(1)`, which is the short form for `f.invoke(1)`.
The Kotlin compiler has to take this convention into account every time it resolves a call `a.foo()`, because `foo` might be either a regular function, or a value that is called via the `invoke` convention.
Earlier we described how the calls `a.foo()` and `foo()` are resolved.
Just to remind you, the compiler builds several groups of possibly applicable functions according to different categories of functions.
These groups are ordered: functions from different groups have different priorities.
The applicable function with the highest priority is the result.
You can see now that this description ignores the `invoke` convention: only regular functions are considered.
In fact, the algorithm doesn't change at all for the `invoke` convention.
Local variables and properties that can be called by this convention are divided into similar groups.
Thus more groups are created, while all the rest stays the same.
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.
The examples below will illustrate that.
A member property of function type has higher priority than an extension function with the same name:
[source,kotlin]
----
class A {
val foo: () -> Int = { 1 }
}
fun A.foo() = 2
fun test(a: A) {
a.foo() <1>
}
----
<1> The member property of function type is called
In this case the Kotlin compiler constructs the following groups:
1. The first group contains a property `foo` with the `invoke` function.
Note that both the property and the `invoke` function are members.
The property is a member of the `A` class.
The `invoke` function is a member of the `Function0` interface from the standard library, which is similar to `Function1` interface shown above.
2. No local extensions or member extensions with the name `foo` are declared, so the top-level extension `foo` goes next.
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.
Let's see an example of how group priorities are determined:
* Functions go before properties of the same category, so a top-level extension named `foo` has higher priority then a top-level extension property `foo` of function type.
* The priority of both the property and the `invoke` function matters.
Thus if the `invoke` function is declared as an extension, the member property with this function goes after the group "extension functions".
[source,kotlin]
----
class A {
val foo: CallableFoo = CallableFoo()
}
fun A.foo() = 1
class CallableFoo
operator fun CallableFoo.invoke() = 2
val A.foo: () -> Int
get() = { 3 }
fun test(a: A, foo: A.() -> Int) {
a.foo()
}
----
The following groups are created to resolve the call `a.foo()`:
0. The parameter `foo` of the function `test` that has the type `A.() -> Int` can be called as extension function and goes in the first group.
This parameter will actually be called in the example above.
1. The top-level extension function #1 goes next.
2. We have two top-level extension properties named `foo` in the context, for each of them the `invoke` function is available.
Two groups are created.
The first one contains the member property `val foo: CallableFoo` together with the function `fun CallableFoo.invoke()`.
The second group contains the property `val A.foo: () -> Int` together with the member function `invoke` of the class `Function0<Int>`.
These properties belong to different groups with different priorities, because the first property is a member, while the second one is an extension.
Note that despite being a member, property `foo` of the type `CallableFoo` goes after regular extension functions, because only the extension function `invoke` is available in the context.
Note that to resolve a call with implicit receiver we still prioritize groups by their receivers.
Thus the functions and properties of closer receiver have higher priority:
[source,kotlin]
----
class A { fun foo() = 2 }
class B { val foo: () -> Int = { 1 } }
fun test(a: A, b: B) {
with (a) { with (b) { foo() } }
}
----
The call `foo()` in the example above is resolved to a property of the class `B`, because the receiver of the type `B` is closer than the receiver of the type `A`.
[NOTE]
.Resolving a call with three implicit receivers
====
When the compiler resolves a property by the `invoke` convention, it resolves separately the property and the `invoke` function.
The property can be a member extension, and the `invoke` function might require an extension receiver as well.
Thus we can construct a call with three implicit receivers:
[source,kotlin]
----
class A {
val B.foo: C.() -> Unit
get() = { println("Implicit receivers: " +
"$this; ${this@foo}; ${this@A}") }}
}
class B
class C
fun test(a: A, b: B, c: C) {
with (a) { with (b) { with (c) { foo() } } } <1>
}
----
<1> Three implicit receivers `A`, `B` and `C` are used to resolve `foo`
In this example `foo` is declared as an extension property to `B` that has type `C.() -> Unit`.
Its getter returns a lambda with receiver.
Inside this lambda we can access its receiver of type `C` simply by `this`.
Also, we can access property's receiver of type `B` by specifying a label `this@foo` and the instance of outer class by writing `this@A`.
While resolving the call `foo` the compiler has to ensure that all necessary receivers are available: `A` and `B` to resolve a property `foo`, and `C` to call the hidden invoke function.
====
=== Name resolution and SAM conversion
Kotlin supports SAM conversions.
If a Java method has a parameter of the SAM interface (an interface with a single abstract method), in Kotlin you can pass a lambda argument instead.
This section describes how it's supported in the name resolution algorithm.
For each Java method taking SAM interface as a parameter, the Kotlin compiler generates an additional syntactic method.
This new method takes a parameter of the corresponding function type and delegates to the original method.
Note that this syntactic method exists only during the name resolution process and isn't represented in the bytecode.
If we wrote the generated syntactic member in Java directly, it could look like this:
[source, java]
----
public class J {
/* original method */
public int foo(Runnable r) { return 1; }
/* syntactic method generated by the Koltin compiler for name resolution */
public int foo(final Function0<Unit> f) {
return foo(new Runnable() {
public void run() {
f.invoke();
}
});
}
}
----
Both of these methods (original and syntactic) participate in the regular name resolution process.
Thus if you call `foo` and pass lambda as a parameter, the syntactic method will be chosen:
[source, kotlin]
----
fun test(j: J) {
println(j.foo { }) // 1
}
----
Note that as there is no real `foo` method taking lambda as a parameter, the necessary conversion happens on the call site.
(Under the hood the bytecode is optimized, so an object of the required SAM interface is created straight away instead of an object of the Kotlin function type.)
_Finding the most specific member for the group of methods_ slightly changes when syntactic methods appear.
Imagine that the `J1` class explicitly declares both the method taking `Runnable` and the method taking `Function0`.
In this case the method taking `Function0` should be chosen without any ambiguity:
[source, java]
----
public class J1 {
public int foo(Runnable r) { return 1; }
public int foo(Function0<Unit> f) { return 2; }
}
----
[source, kotlin]
----
fun test(j1: J1) {
println(j1.foo { }) // 2
}
----
To achieve such behaviour the syntactic `foo` (returning 1) should have less priority than the declared `foo` (returning 2).
Finding the most specific member is divided into two steps:
Step 1.
`members + syntactic members -> most specific`
The most specific candidate is found for the group consisting of both members and syntactic members.
If such candidate exists, it's the result.
Otherwise, the result is determined in step 2.
Step 2.
`members -> most specific`
The most specific candidate is found only for members (without syntactic members).
If no appropriate member is found, the name resolution algorithm proceeds as described earlier in this document
(tries to find the appropriate function among local extensions, member extensions, etc.).
Now we can see how this process works for `J` and `J1` classes defined above.
For `j.foo()` call the first step returns the result, because the syntactic member for `foo` is chosen as the most specific candidate.
However, for `j1.foo()` the first step finishes with ambiguity, because two `foo` methods (1-syntactic and 2-declared explicitly) have the same signature.
Then the second step produces the result, which is the foo-2 method, because only declared methods are considered.
[NOTE]
.Finding the most specific member with SAM conversion in Kotlin 1.0
====
In Kotlin 1.0 syntactic methods were generated differently: they were generated as extensions.
That was leading to unpleasant consequences if another suitable member (taking `Object`) was declared.
The class `J2` illustrates the problem:
[source, java]
----
public class J2 {
public int foo(Runnable r) { return 1; }
public int foo(Object o) { return 3; }
}
----
[source, java]
----
fun test(j2: J2) {
// Kotlin 1.0 prints 3 - surprise!
// Kotlin 1.1 prints 1 as expected
println(j2.foo {})
}
----
In Kotlin 1.0 foo-3 is chosen, because it's a member, while the syntactic method for foo-1 is an extension (and a member is always chosen over an extension).
Thus in Kotlin 1.1 the algorithm was slightly changed, and the syntactic methods are generated as syntactic members as desribed above.
====
We discussed how the Kotlin compiler chooses the function that should be called in each invocation.
Generally we expect that you write code without confusing overloaded functions.
However, we wanted to clarify the compiler choice in the cases when it might be unclear.