skip to content

Give a concrete scenario where you MUST use `noinline`, and explain why the compiler forces it.

level: middleimportance: must knowfreq 48%

answer

  1. Inlined lambda = no object to use
  2. store / return / pass-to-non-inline => noinline
  3. Error: 'Illegal usage of inline-parameter'
  4. Invoking is fine without noinline
  5. Pass to another inline fn is also fine

basics

~20 s

You need noinline when you want to keep the lambda as a value — for example to return it, store it in a list, or hand it to another function that isn't inline. The compiler refuses to compile those uses on an inlined lambda because there's no object to use.

solid answer

~40 s

An inlined lambda has no runtime object — its body is spliced into the call site — so any operation that treats it as a value is impossible. The compiler emits an error like "Illegal usage of inline-parameter" ("can't be inlined") when you try to: assign the lambda to a variable, return it, put it in a collection, or pass it to a non-inline function. Marking the parameter `noinline` materializes it as a `FunctionN` object so those uses become legal. Classic case: a higher-order helper that runs one callback now and defers another for later execution. The deferred one must be `noinline` because it is stored/returned. The immediately-invoked one can stay inlined for zero allocation.

code

kotlin · 7 lines
kotlin
inline fun runAndRemember(
    immediate: () -> Unit,
    noinline deferred: () -> Unit
): () -> Unit {
    immediate()
    return deferred // legal only because deferred is noinline
}

go deeper

for a junior

Recognizes you need noinline to keep a lambda as a value you can store or return.

for a middle

Lists the exact operations that require it and gives a working deferred-callback example.

for a senior

Explains the no-object codegen reason, the chaining-through-inline exception, and the allocation cost saved by inlining the rest.

for a principal

Weighs whether the deferred-callback design should be inline at all, vs. exposing a plain function, based on call-site allocation profiles.

## Why the compiler forces it When the compiler inlines a lambda, it literally pastes the lambda body at each place you call `param()` inside the inline function. There is **no `FunctionN` instance** representing that lambda. So the moment you do anything that needs the object — not just call it — the compiler has nothing to give you and reports an error such as `Illegal usage of inline-parameter` / `Inline parameter cannot be used as a value`. Operations that need the object form (and thus require `noinline`): - assigning it: `val f = param` - returning it: `return param` - storing it: `list.add(param)` - passing it to a **non-inline** function: `register(param)` Operations that are fine on an inlined lambda: - invoking it: `param()` - passing it to **another inline** function as an inline argument ## Concrete scenario — deferred callback ```kotlin private val pending = mutableListOf<() -> Unit>() inline fun schedule( runNow: () -> Unit, // inlined: invoked immediately noinline runLater: () -> Unit // must be noinline: stored for later ) { runNow() pending.add(runLater) // needs a real object -> noinline required } ``` Without `noinline` on `runLater`, `pending.add(runLater)` fails to compile because `runLater` is not a value. `runNow` stays inlined, so calling `schedule` allocates only the single `runLater` object instead of two. ## Passing to a non-inline function ```kotlin fun consume(block: () -> Unit) = block() // NOT inline inline fun forward(noinline block: () -> Unit) { consume(block) // needs the object; noinline makes it legal } ``` ## Mental model Ask: "Do I only **call** this lambda, or do I treat it as a **thing**?" Calling => leave it inlined. Treating it as a thing (store/return/pass to non-inline) => mark it `noinline`.

  • Why is passing an inlined lambda to ANOTHER inline function allowed without noinline?
    Because the receiving function also inlines it, so it never needs an object form — the inlining chains through. Only a non-inline receiver forces a real object.
  • What error message hints you need noinline?
    An 'Illegal usage of inline-parameter' / 'inline parameter cannot be used as a value' compile error at the spot where you store, return, or pass the lambda.

saying these in an interview costs you the question

  • Claiming you can store/return an inlined lambda without noinline
  • Saying passing to any other function works (it must be inline)
  • Not knowing the compiler hard-errors, not just warns
  • Marking every lambda noinline 'to be safe', losing inline benefits

context