Added separate notes for name resolution motivation

Addressed some comments on the main article
This commit is contained in:
Svetlana Isakova
2016-03-31 13:23:46 +03:00
parent 56ef98ee29
commit 4c30bcfca0
2 changed files with 64 additions and 4 deletions
+6 -4
View File
@@ -243,7 +243,9 @@ Now let's discuss the specific steps the compiler performs to resolve a call:
Members is an example of a such group - the one with the highest priority. Members is an example of a such 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. * 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.
The name resolution for each group works like in Java.
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. 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. 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.
@@ -254,10 +256,10 @@ Below we describe the groups of functions that are created to resolve `a.foo()`:
All overloaded member functions with the name `foo` have the same priority and go in one group. All overloaded member functions with the name `foo` have the same priority and go in one group.
2. _Local extension functions._ 2. _Local extension functions._
Local extensions have higher priority than other extensions, however, even they can't go before members. Several groups of local extensions are created.
Several groups of local extension functions are created.
The functions are prioritized by scopes: more local functions have higher priority and go earlier. 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. 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_. 3. _Member extensions_.
Let's say several implicit receivers are available in the context. Let's say several implicit receivers are available in the context.
@@ -356,7 +358,7 @@ Such function may be located in the same file as the usage or in the other files
3. _Star-imports_. 3. _Star-imports_.
By using `*` you import all contents of a package. By using `*` you import all contents of a package.
The functions imported in this way have lower priority then the functions imported directly. Note that the functions imported in this way have lower priority then the functions imported directly.
4. _Function from stdlib_. 4. _Function from stdlib_.
The Kotlin standard library contains lots of extension functions. The Kotlin standard library contains lots of extension functions.
+58
View File
@@ -0,0 +1,58 @@
## Motivation
#### Locals have the highest priority
A variable of function type goes before members:
```
class A { fun foo() = 1 }
fun test(a: A, foo: () -> Int) {
with (a) {
foo()
}
}
```
In anonymous objects local variables are chosen, not members:
```
interface A {
val foo: Int
}
fun createA(foo: Int) = object : A {
override val foo = foo
}
```
#### Top-level scope chain
The priorities: explicit imports; functions in the same package; star-imports; function from stdlib.
Explicit import should hide descriptors imported by `*`.
There is no scope for file, because moving a function to another file in the same package should not change the resolution.
The function imported explicitly goes before the function from the same package; the latter one may live in another file.
#### The order of implicit receivers
See the discussion here: https://youtrack.jetbrains.com/issue/KT-10510.
## Technical notes
When we resolve a property `foo` for a call `foo()` we don't stop on the first property, but instead we collect all variables with the name `foo` and for each of them try to find the `invoke` function:
```
class A {
val foo: () -> Unit = { println("Hello world!") }
}
fun test(foo: Int) {
with(A()) {
foo // parameter
foo() // property + invoke
}
}
```