Note: This proposal has nothing to with the currently experimental inline classes feature, even though I’ll use the term here with a different meaning. If this feature gets considered, it’ll have to be named something else since ‘inline classes’ is taken.
Is it possible to reify a generic parameter at class level by inlining a whole class?
Example:
[inline/some other keyword] class Something<reified A> {
// Some functionality
// Usage of the reified parameter
fun returnSomething(value : Any) : Something<A> =
if (value is A) // type check possible with reified parameter
value
else
// Some other way to obtain Something<A>
}
// Usage of the class:
val someString = Something<String>();
// Generated code:
class Something$String {
fun returnSomething(value : Any) : Something$String = // Type parameter replaced
if (value is String)
value
else
// Some other way to obtain Something$String
}
I understand that this could increase the class count significantly, especially for more than one type parameter. Another problem would be if the class with the generic type parameter is declared in some library and used (i.e. supplied with the type parameter) elsewhere.
The solution to the former is that the feature would obviously be optional, so developers could be told of the implications, and then they may use it if they can accept the large class count (or if they aren’t using it with too many type parameters)
The solution to the latter is to produce two versions of the class in the bytecode. One would be a normal generic class with erased type parameters, usable from Java (as is done with inline functions). The second could be a template class especially marked for Kotlin code somehow, and then when someone imports the library and uses the class, his project could inline only the type parameters he has used in his code, e.g. if he has used Something<String>
, Something<Int>
and Something<Double>
only, then only Something$String
, Something$Int
and Something$Double
, are generated, but no others.
I suppose it could also be possible to have (as with inline functions) some reified type parameters and some not, so: [inline/other keyword] class Somethings<reified A, B>
, if used as val someStringAndInt = Something<String, Int>
, would result in the generation of the class Something$String<B>
with the second parameter erased as usual.
I have no idea whether this is feasible or not, so I thought I’d find out. I’ve also filed an issue at YouTrack: KT-33213.