From 0abf56c9acaa588987d55f93032401711c95b2cd Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Thu, 18 Dec 2014 14:21:44 +0300 Subject: [PATCH] Spec document for reified type parameters --- spec-docs/reified-type-parameters.md | 60 ++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 spec-docs/reified-type-parameters.md diff --git a/spec-docs/reified-type-parameters.md b/spec-docs/reified-type-parameters.md new file mode 100644 index 00000000000..c58427b8465 --- /dev/null +++ b/spec-docs/reified-type-parameters.md @@ -0,0 +1,60 @@ +# Reified Type Parameters + +Goal: support run-time access to types passed to functions, as if they were reified (currently limited to inline functions only). + +## Syntax + +A type parameter of a function can be marked as `reified`: + +``` kotlin + +inline fun foo() {} +``` + +## Semantics, Checks and Restrictions + +**Definition** A well-formed type is called *runtime-available* if +- it has the form `C`, where `C` is a classifier (object, class or trait) that has either no type parameters, or all its type parameters are `reified`, with the exception for class `Nothing`, +- it has the form `G`, where `G` is a classifier with `n` type parameters, and for every type parameter `Ti` at least one of the following conditions hold: + - `Ti` is a `reified` type parameter and the corresponding type argument `Ai` is a runtime-available type, + - `Ai` is a *star-projection* (e.g. for `List<*>`, `A1` is a star-projection); +- it has the form `T`, and `T` is a `reified` type parameter. + +Examples: +- Runtime-available types: `String`, `Array`, `List<*>`; +- Non-runtime-available types: `Nothing`, `List`, `List` (for any `T`) +- Conditional: `T` is runtime-available iff the type parameter `T` is `reified`, same for `Array` + +Only runtime-available types are allowed as +- right-hand arguments for `is`, `!is`, `as`, `as?` +- arguments for `reified` type parameters *of calls* (for types any arguments are allowed, i.e. `Array>` is still a valid type). + +As a consequence, if `T` is a `reified` type parameter, the following constructs are allowed: +- `x is T`, `x !is T` +- `x as T`, `x as? T` +- reflection access on `T`: `javaClass()`, `T::class` (when supported) + +Restrictions regarding reified type parameters: +- Only a type parameter of an `inline` function can be marked `reified` +- The built-in class `Array` is the only class whose type parameter is marked `reified`. Other classes are not allowed to declare `reified` type parameters. +- Only a runtime-available type can be passed as an argument to a `reified` type parameter + +Notes: +- No warning is issued on `inline` functions declaring no inlinable parameters of function types, but having a `reified` type parameter declared. + +## Implementation notes for the JVM + +In inline functions, occurrences of a `reified` type parameter `T` are replaced with the actual type argument. + +``` kotlin +open class TypeLiteral { + val type: Type + get() = (javaClass.getGenericSuperclass() as ParameterizedType).getActualTypeArguments()[0] +} + +inline fun typeLiteral(): TypeLiteral = object : TypeLiteral() {} // here T is replaced with the actual type + +typeLiteral().type // returns 'class java.lang.String' +typeLiteral>().type // returns '[Ljava.lang.String;' +typeLiteral>().type // returns 'java.util.List' +```