Skip to content

Commit

Permalink
Update LHS resolution algorithm with a special case for objects (#5)
Browse files Browse the repository at this point in the history
Reword the whole algorithm, to (hopefully) improve readability
udalov committed Aug 10, 2016
1 parent f8e6ffd commit 867de35
Showing 1 changed file with 12 additions and 8 deletions.
20 changes: 12 additions & 8 deletions proposals/bound-callable-references.md
Original file line number Diff line number Diff line change
@@ -72,8 +72,8 @@ The LHS may now be interpreted as an expression, or a type, or both.
SimpleName::foo // expression (variable SimpleName) or type (class SimpleName)
Qualified.Name::foo // expression or type
Nullable?::foo // type (see section Nullable references below)
Generic<Arg>::foo // type
Nullable?::foo // type (see section "Nullable references" below)
Generic<Arg>::foo // type (see section "Calls to generic properties" below)
Generic<Arg>()::foo // expression
this::foo // expression
@@ -82,13 +82,17 @@ The LHS may now be interpreted as an expression, or a type, or both.
(ParenNullable)?::foo // type
```

The semantics are different when the LHS is interpreted as an expression or a type, so we establish a priority of one over another when both interpretations are applicable.
The algorithm is the following:
The semantics are different when the LHS is interpreted as an expression or a type, so we introduce the following algorithm to choose the resulting interpretation when both are applicable:

1. Try interpreting the LHS as an **expression** with the usual resolution algorithm for qualified expressions.
If the result represents a companion object of some class, continue to p.2.
Otherwise continue resolution of the member in the scope of the expression's type.
2. Resolve the unbound reference with the existing algorithm.
1. Type-check the LHS as an **expression**.
- If the result represents a _companion object of some class_ specified with the short syntax (via the short/qualified name of the containing class), discard the result and continue to p.2.
- If the result represents an _object_ (either non-companion, or companion specified with the full syntax: `org.foo.Bar.Companion` or just `Bar.Companion`), remember the result and continue to p.2.
- Otherwise the resolution of the LHS is complete and the result is the type-checked expression. Note that the resolution of the LHS is finished at this point even if errors were reported.
2. Resolve the LHS as a **type**.
- If the resulting type refers to the same object that was obtained in the first step, complete the resolution with the result obtained in the first step. In other words, the result is the object type-checked as expression, and the object instance will be bound to the reference.
- Otherwise the result is the resolved type and the reference is unbound.

> If there were no `object`s or `companion object`s in Kotlin, the algorithm would be very simple: first try resolving as expression, then as type. However, this would not be backwards compatible for a very common case: in an expression like `Obj::foo`, without any changes to the source code an object `Obj` might now win the resolution where previously (in Kotlin 1.0) a completely different class `Obj` had been winning. This is possible when you have a class named `Obj` and an object `Obj` in another package, coming from a star import.
Examples:
```

0 comments on commit 867de35

Please sign in to comment.