skip to content

noinline

noinline opts a single lambda parameter out of inlining, so it stays a real object you can store in a field or pass to another function. Interviewers ask when you would need it, and the answer is any time the lambda outlives the call.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

What does the `noinline` modifier do when applied to a lambda parameter of an `inline` function?

level: juniorimportance: must knowfreq 55%

answer

  1. Keeps one lambda as a real Function object
  2. Lets you store / return / pass-onward the lambda
  3. Only meaningful inside an inline function
  4. Other lambdas still get inlined
  5. Redundant + warned on non-inline functions

basics

~20 s

It tells Kotlin NOT to inline that one lambda. Instead the lambda stays a normal object you can store in a variable or pass to another function, while the other lambdas in the inline function are still inlined.

solid answer

~40 s

When you mark a function `inline`, the compiler copies the function body and each lambda argument's body directly into the call site, so no lambda object is allocated. But sometimes you need a lambda to remain a real `Function` object — e.g. to store it in a field, return it, or pass it to a non-inline function. Marking that specific parameter `noinline` opts it out of inlining: it becomes an ordinary `FunctionN` instance. Other lambda parameters of the same function are still inlined. `noinline` is only meaningful on a lambda/function-type parameter of an `inline` function; on a non-inline function every lambda is already a real object, so the keyword is redundant there and the compiler warns.

code

kotlin · 7 lines
kotlin
inline fun run2(first: () -> Unit, noinline second: () -> Unit): () -> Unit {
    first()        // body copied in, no object
    return second  // returned as an object
}

val later = run2({ println("now") }, { println("later") })
later()  // prints "later"

go deeper

for a junior

Knows noinline keeps a specific lambda as a normal object so it can be stored or passed on.

for a middle

Explains it's per-parameter, only meaningful inside inline, and how it coexists with inlined parameters.

for a senior

Connects it to the allocation/Function-object model and contrasts cleanly with crossinline and the inline cost model.

for a principal

Frames noinline as an API-design and codegen tradeoff lever and reasons about when an inline+noinline split beats a plain function.

## What `inline` does first When a function is declared `inline`, the Kotlin compiler does not generate a normal call. Instead it copies the function's body — and the body of each lambda you pass — straight into the call site. The benefit: passing a lambda to a non-inline function normally allocates a `Function` object (a class implementing `kotlin.Function0`, `Function1`, etc.); inlining removes that allocation and the virtual `invoke` call. ## The problem `noinline` solves Inlining a lambda means the lambda has **no object form** inside the function body — there is nothing to assign to a variable, store in a field, or pass to another (non-inline) function. If your inline function needs to treat one of its lambdas as a real value, that lambda cannot be inlined. `noinline` is the per-parameter opt-out. Marking a lambda parameter `noinline` keeps it as a concrete `FunctionN` object, so you can: - store it in a `val`/field or a collection - return it from the function - pass it onward to a function that is **not** inline Meanwhile, any **other** lambda parameters of the same inline function are still inlined as usual. ```kotlin inline fun transform( inlined: () -> Unit, // inlined into call site noinline stored: () -> Unit // kept as a real object ): () -> Unit { inlined() return stored // legal ONLY because `stored` is noinline } ``` ## Where it is allowed `noinline` only applies to a function-type (lambda) parameter of an `inline` function. On a regular (non-inline) function, every lambda is already a heap object, so `noinline` is redundant and the compiler emits a warning. It is unrelated to value parameters of other types. ## Relationship to `crossinline` Both modify a lambda parameter of an inline function but in opposite directions: `crossinline` keeps the lambda inlined while forbidding non-local returns; `noinline` un-inlines the lambda entirely. You reach for `noinline` when you need the lambda as a value; you reach for `crossinline` when you still inline it but call it from a nested context.

  • If a function is NOT marked inline, does `noinline` do anything?
    No. In a non-inline function all lambdas are already real objects, so `noinline` is redundant and the compiler warns about it.
  • Can you mix inlined and noinline lambda parameters in one function?
    Yes — that's the point. You mark only the lambdas you need as objects `noinline`; the rest stay inlined.

Inlining is photocopying the recipe steps into the page; noinline keeps that one step as a separate index card you can hand to someone else.

saying these in an interview costs you the question

  • Saying `noinline` makes the whole function not inline (it's per-parameter)
  • Claiming `noinline` works on regular functions usefully
  • Confusing `noinline` with `crossinline`
  • Thinking `noinline` forbids non-local returns (that's crossinline)

context

open as a page

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

level: middleimportance: must knowfreq 48%

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.

open as a page

Compare `noinline` and `crossinline`: what does each control, and when do you pick one over the other?

level: middleimportance: should knowfreq 50%

basics

~20 s

Both apply to a lambda parameter of an inline function. noinline un-inlines the lambda so it becomes a real object you can store or pass on. crossinline keeps it inlined but bans return that would exit the caller, which is needed when the lambda runs from another context.

open as a page

What are the codegen and performance implications of marking a lambda `noinline`, and how does it interact with variable capture?

level: seniorimportance: should knowfreq 32%

basics

~20 s

A noinline lambda becomes a real object, so it costs an allocation and a virtual call, just like a lambda passed to any normal function. If it captures no variables Kotlin can reuse a single shared instance; if it captures, a new object is created each call.

open as a page

You're designing a higher-order API. How do you decide between making a function `inline` with a `noinline` parameter versus just writing a plain function?

level: seniorimportance: nice to knowfreq 22%

basics

~20 s

Make it inline only if at least one lambda benefits from inlining (hot calls, non-local returns, or reified types). Use noinline for the one lambda you must keep as an object. If every lambda needs to be an object, just write a normal function.

open as a page