From 4c30bcfca012c6cdd17641d0813be18dcd330f40 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Thu, 31 Mar 2016 13:23:46 +0300 Subject: [PATCH] Added separate notes for name resolution motivation Addressed some comments on the main article --- spec-docs/NameResolution.adoc | 10 +++-- spec-docs/name-resolution-motivation.md | 58 +++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 spec-docs/name-resolution-motivation.md diff --git a/spec-docs/NameResolution.adoc b/spec-docs/NameResolution.adoc index 03026941735..5591ab0b5ba 100644 --- a/spec-docs/NameResolution.adoc +++ b/spec-docs/NameResolution.adoc @@ -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. * 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. 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. 2. _Local extension functions._ -Local extensions have higher priority than other extensions, however, even they can't go before members. -Several groups of local extension functions are created. +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. @@ -356,7 +358,7 @@ Such function may be located in the same file as the usage or in the other files 3. _Star-imports_. 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_. The Kotlin standard library contains lots of extension functions. diff --git a/spec-docs/name-resolution-motivation.md b/spec-docs/name-resolution-motivation.md new file mode 100644 index 00000000000..9fdc95f25d4 --- /dev/null +++ b/spec-docs/name-resolution-motivation.md @@ -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 + } +} +``` \ No newline at end of file