File: reified-type-parameters.md

package info (click to toggle)
kotlin 1.3.31%2Bds1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 109,908 kB
  • sloc: java: 454,756; xml: 18,599; javascript: 10,452; sh: 513; python: 97; makefile: 69; ansic: 4
file content (62 lines) | stat: -rw-r--r-- 3,023 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# 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<reified T>() {}
```

## 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<A1, ..., An>`, 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<String>`, `List<*>`;
- Non-runtime-available types: `Nothing`, `List<String>`, `List<T>` (for any `T`)
- Conditional: `T` is runtime-available iff the type parameter `T` is `reified`, same for `Array<T>`

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<List<String>>` 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>()`, `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.
If actual type argument is a primitive type, it's wrapper will be used within reified bytecode.

``` kotlin
open class TypeLiteral<T> {
    val type: Type
        get() = (javaClass.getGenericSuperclass() as ParameterizedType).getActualTypeArguments()[0]
}

inline fun <reified T> typeLiteral(): TypeLiteral<T> = object : TypeLiteral<T>() {} // here T is replaced with the actual type

typeLiteral<String>().type // returns 'class java.lang.String'
typeLiteral<Int>().type // returns 'class java.lang.Integer'
typeLiteral<Array<String>>().type // returns '[Ljava.lang.String;'
typeLiteral<List<*>>().type // returns 'java.util.List<?>'
```