inline functions and reified

Kotlin language Senior Kotlin 2.0+ API 24+ Reviewed By Best Latest Apps

Pick the fix

This doesn't compile: 'Cannot check for instance of erased type T'. What's the fix?

fun <T> List<Any>.firstOfType(): T? =
    firstOrNull { it is T } as T?
Options
Hint 1 of 1

What does reified require?

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A Make it inline fun <reified T> List<Any>.firstOfType(): T?

Correct. reified needs inline, and then is T works.

Why not the others?
  • B Add @Suppress("UNCHECKED_CAST"). Suppressing a warning doesn't make an erased check possible.
  • C Use T::class.java instead. Also needs reified.
  • D Make T non-null with T : Any. The type is still erased.

30-second answer

An inline function's body, and the lambdas passed to it, are copied into each call site. That removes the cost of allocating lambda objects and allows return from inside the lambda to return from the caller. Because the code is copied, the compiler knows the actual type at each call, which is what makes reified T possible, so you can write is T or T::class.

Practise saying it · 35 s. No recording, just a timer

Explain inline and reified.

Say your answer out loud, then check which of these points you covered:

  • Body and lambdas copied to the call site
  • No lambda allocation, non-local return
  • reified needs inline
  • Keep inline functions small

Deep dive

Use inline for small higher-order functions; inlining big functions bloats the code.

noinline keeps one lambda parameter as an object; crossinline forbids non-local returns when the lambda is called from another context.

Generic types are erased at runtime, so without reified you can't check is T.

Public inline functions can't use private members, because their body is copied into other modules.

A reified helper Compile-checked · Kotlin 2.4.21
inline fun <reified T> List<Any>.firstOfType(): T? =
    firstOrNull { it is T } as T?

fun main() {
    println(listOf(1, "two", 3.0).firstOfType<String>())
}

Common mistakes

  • Marking big functions inline for 'speed'.
  • Expecting reified to work without inline.
  • Using a non-local return in a lambda that's passed to another thread.

Senior take & follow-ups

Explain the copy-into-call-site model; everything else follows from it.

Follow-up questions

Think of your answer first, then open the hint.

  1. What does crossinline prevent?

    Show hint

    Non-local returns from a lambda that will be called in another context.

  2. Why can't a normal generic function check is T?

    Show hint

    Type arguments are erased at runtime.

Suggest a fix if something here is wrong or out of date.