Inline modifier and reified

Hi!
This is my first topic so thanks for having accepted me. Studying Kotlin I wondered why a type reification requires an inlined function. I’ve searched everywhere online but no one has explained this clearly so I am not able to understand. Why the compiler is not able to reify a type parameter without inlining the function first?

Could you help me please?

Thank you in advance
Giorgio

This is a problem of the jvm. What happens is that on the jvm itself does not have generic types (this is called type erasure). So at runtime List<Foo> becomes List and List<Bar> also becomes List. Generic information is only available to the compiler, it isn’t available at runtime. This also means that a function call foo<Int>() at runtime is just foo() so you can no longer use the type parameter inside of the function. You can use it to only for stuff that requires the type parameter at compile time, but not at runtime.

fun <T> foo(arg1: T) {
    val f = listOf<T>(arg1)   // ok, T is only used at compile time
    if(f.first is T)     // error, this requires T at runtime, so it can't be done
        TODO()
}

To reify a type parameter kotlin inlines the type. That way the type is still known at runtime, but this requires the entire function to be inlined. I hope this helps. Let me know if something is still unclear.

2 Likes

Hi @Wasabi375,
thanks for your exhaustive response, I am almost there. So inline is needed to save the type before it is erased by JVM, but it cannot be done directly inside the called function.
Summing up, reified cannot be used without inline because the reification is based on inlining, right?

Yes, inlining is a precondition for reification.

You might have (rightfully) assumed that reification should be possible in some cases without inlining. But without jvm runtime support, how would the compiler do it? The compiler would need to generate code for every invocation of a generic function. This code generation would come at a very big cost if done automatically for every generic function. This cost is made obvious by requiring reified generic functions to be inline.

1 Like

Thank you very much! @fatjoe79
You two have erased my doubts, better than a JVM.

Have a good day

1 Like

It is probably worth noting that there is another option to reified types that works without inline. Most things you can do with a reified type can also be done using a Class instance.

inline fun <reified T>foo(a: Any): Boolean = a is T

fun foo(a: Any, c: Class<*>): Boolean = c.isAssignableFrom(a)
foo("test", String::class.java)

This works using reflection, and is how java solves this problem. However reflection can have bad performance and might not work on every system (normal windows/linux/macos/android should be fine though).

Passing a Class instance is the traditional Java approach to this sort of problem. But it has disadvantages:

  • It loses information on any type parameters that the type itself has (e.g. List<…>)
  • It loses information on whether the type is nullable.
  • It can’t be inferred by the compiler.
  • Reflection can be inefficient.
1 Like