Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reword callable reference and class literal resolution algorithm, explain some corner cases (#5) #43

Merged
merged 7 commits into from
Aug 15, 2016
20 changes: 16 additions & 4 deletions proposals/bound-callable-references.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,24 @@ fun test() {
}
```

Once the LHS is type-checked and its type is determined to be `T`, the type of the whole class literal expression is `kotlin.reflect.KClass<T'>` where `T'` is a type obtained by _substituting `T`'s arguments with star projections (`*`)_. Example:
Once the LHS is type-checked and its type is determined to be `T`, the type of the whole class literal expression is `KClass<erase(T)>`, where `erase(T)` represents the most accurate possible type-safe representation of the type `T` and is obtained by substituting `T`'s arguments with star projections (`*`), except when the type is an array.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type-arguments of arrays are not fully known at runtime either: their nullability is unclear. Does it matter in this context?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does matter, and we may revisit it in the future, but type-checking arrayOfStrings::class to KClass<Array<*>> would be rather unhelpful from Java user's point of view. We've briefly discussed this with @erokhins and decided (for now) to type-check arrayOfStrings::class to KClass<Array<String>>. We should discuss this in detail later anyway.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note in JS we don't know anything about type-arguments of arrays at runtime.


More formally, let `T` = `C<A1, ..., AN>`, where `C` is a class and `N`, the number of type arguments, might be zero. `erase(T)` is then defined as follows:
- if `C` = `kotlin.Array`:
- if `A1` is a projection of some type (covariant, contravariant, or star), `erase(T)` = `kotlin.Array<*>`
- otherwise `erase(T)` = `kotlin.Array<erase(A1)>`
- otherwise `erase(T)` = `C<*, ..., *>`

Examples:
```
fun test() {
"a"::class // KClass<String>
listOf("a")::class // KClass<List<*>> (not "KClass<List<String>>"!)
mapOf("a" to 42)::class // KClass<Map<*, *>>
"a"::class // KClass<String>
listOf("a")::class // KClass<List<*>> (not "KClass<List<String>>"!)
listOf(listOf("a"))::class // KClass<List<*>> (not "KClass<List<List<String>>>"!)
mapOf("a" to 42)::class // KClass<Map<*, *>>
arrayOf("a")::class // KClass<Array<String>>
arrayOf(arrayOf("a"))::class // KClass<Array<Array<String>>>
arrayOf(listOf("a"))::class // KClass<Array<List<*>>>
}
```

Expand Down