Inside `inline fun <reified T> a()` you call another generic helper `b<T>()`. What must be true of `b` for this to compile, and why?
answer
- reified can only flow into reified
- inline reified -> inline reified chains
- reified into plain generic = allowed but erased
- plain generic into reified = compile error
- 'Cannot use X as reified type parameter'
basics
~20 sIf b also needs the real type (it's reified), then b must itself be an inline reified function. A reified type can only be passed to another reified parameter, because only there is the concrete class still known.
solid answer
~40 sWithin `inline fun <reified T> a()`, `T` behaves like a concrete type, so you may forward it to another function `b<T>()`. The rule depends on `b`: if `b`'s type parameter is **also `reified`** (so `b` is itself `inline`), the substitution chains — both bodies get inlined and `T` flows through as the concrete class. If `b` is an ordinary generic (`fun <U> b()`), you can still call `b<T>()`, but inside `b` that `U` is erased again; you cannot use `b` to recover `T::class`. The compiler **forbids** passing a non-reified type parameter as a reified argument: a plain `fun <X> outer()` cannot call `b<X>()` when `b` expects `reified`, error: *"Cannot use 'X' as reified type parameter. Use a class instead."* Reified-ness propagates only through an unbroken chain of inline reified functions.
code
kotlin · 4 linesinline fun <reified U> b(): KClass<*> = U::class
inline fun <reified T> a(): KClass<*> = b<T>() // OK: chain of reified
fun <X> outer() = b<X>() // ERROR: Cannot use 'X' as reified type parametergo deeper
Knows that to keep using the real type you must keep calling reified functions.
States the three cases precisely — reified->reified OK, reified->plain allowed-but-erased, plain->reified error.
Explains why the chain must be unbroken (call-site substitution) and recognizes the exact compiler error and its trigger.
Designs library helper chains so reification propagates cleanly, balancing the proliferation of small inline functions against code size.
## The chaining rule Inside an `inline fun <reified T>`, the parameter `T` is effectively a concrete type at every call site. That lets you forward it to another function: ```kotlin inline fun <reified T> a() = b<T>() ``` Whether this compiles depends on what `b` requires. ### Case 1 — `b` is inline + reified (chain holds) ```kotlin inline fun <reified U> b(): KClass<*> = U::class inline fun <reified T> a(): KClass<*> = b<T>() // OK ``` Both are inlined, so the concrete type substituted for `T` at `a`'s call site is also substituted into the inlined `b`. `U::class` resolves to the real class. Reified-ness **propagates**. ### Case 2 — `b` is an ordinary generic (allowed, but erased) ```kotlin fun <U> b(): String = "erased" // U erased inside b inline fun <reified T> a() = b<T>() // compiles; b just can't see T ``` You can pass a reified `T` where an ordinary type parameter is expected — going from 'more information' to 'less' is fine — but inside `b`, `U` is erased; you've lost reification. ### Case 3 — non-reified source into a reified target (forbidden) ```kotlin inline fun <reified U> b() {} fun <X> outer() = b<X>() // ERROR: Cannot use 'X' as reified type parameter ``` Here `outer` is a plain generic, so `X` is erased — there's no concrete class to substitute into `b`. The compiler rejects it: *"Cannot use 'X' as reified type parameter. Use a class instead."* Even making `outer` inline doesn't help unless `X` is also `reified`. ## Mental model Reification is like a relay baton: it can only be handed from one reified hand to another. The moment it enters an erased (non-reified) generic, the baton is dropped and can't be picked back up downstream. ## Practical takeaway To build helpers that themselves need `T::class`/`is T`, mark **every** function in the call chain `inline` + `reified`. This is why many Kotlin libraries have long chains of small inline reified extensions.
- Can a non-inline generic function call a reified function with its own type parameter?No. Its type parameter is erased, so the compiler errors with 'Cannot use X as reified type parameter'. The whole chain must be inline + reified.
- Is it legal to pass a reified T into an ordinary generic function?Yes — you can always go from reified to erased. But inside that function the parameter is erased again, so reification doesn't carry through.
saying these in an interview costs you the question
- Saying any generic function can forward its type to a reified one
- Thinking marking only the outer function inline propagates reification without reified
- Believing reified survives passing through a non-reified generic
- Confusing 'compiles' with 'reification preserved' in the erased case