Inline function in Kotlin: what it is, syntax and usage

Author: IT Sectr Published: 2026-06-21 Reading time: 9 min

inline function — a Kotlin mechanism where the function body is substituted directly at each call site at compile time. This eliminates the overhead of creating anonymous classes and objects for lambda parameters. According to Kotlin Documentation, 2025, the inline keyword is especially effective for higher-order functions, where each lambda without inlining creates a separate FunctionN object, burdening the garbage collector.

Key Takeaways

  • inline function — a function whose body is inlined at the call site at compile time
  • Overhead reduction — eliminates creating anonymous classes and objects for lambdas
  • Nonlocal return — lambdas inside inline functions can return from the outer function
  • noinline — prevents inlining of specific lambda parameters
  • crossinline — allows nonlocal return but prohibits return from the inline function context

What is inline function in Kotlin?

An inline function is a function marked with the inline keyword. The Kotlin compiler does not create separate bytecode with a call for it — instead, it copies the function body directly into each call site. The main goal is to optimize higher-order functions that accept lambda expressions, since each lambda in a normal situation creates an anonymous Function class object.

According to JetBrains Tech Blog (2024), using inline functions in Kotlin can reduce the number of created objects by 40–60% in functions that intensively use lambdas. In loops and high-load operations (sorting, collection filtering) this provides a measurable performance boost.

Without inline, each lambda compiles into an anonymous class (or an instance of a synthesized functional interface). For lambdas that capture variables, additional wrapper objects are created. Inline functions eliminate all these objects at compile time, replacing them with direct code that accesses local variables without wrappers.

Use inline only for functions with lambda parameters — the Kotlin compiler itself warns if inline does not provide any benefit.

Inline function syntax and how it works

Simply add the inline keyword before the function declaration. The compiler automatically substitutes the function body at the call sites. The function itself continues to exist in bytecode for cases when it is not called directly (for example, from Java code).

kotlin
inline fun Int.repeatAction(action: (Int) -> Unit) {
    for (i in 0 until this) {
        action(i)
    }
}

// Call — lambda code is inlined into the function body
5.repeatAction { index ->
    println("Index: $index")
}

After compilation, the code above will be equivalent to:

kotlin
// What happens after inlining (schematically):
val $this = 5
for (i in 0 until $this) {
    println("Index: $i")
}

No objects are created for the lambda — the action code executes directly. This is the essence of the optimization: instead of calling Function.invoke() — a direct insertion of the code with the lambda body.

Verification through decompilation

To verify inlining, open Tools > Kotlin > Show Kotlin Bytecode in IntelliJ IDEA and click Decompile. You will see that instead of calling repeatAction with a lambda, a direct insertion of the function body with a for loop is generated.

The lambda overhead problem and its solution

Each lambda in Kotlin compiles into one of three variants. First — if the lambda does not capture variables, it becomes a static method of the class where it is declared. Second — if it captures one variable, an anonymous class is created. Third — if it captures multiple variables, an anonymous class with fields for each captured variable is created.

Lambda typeWithout inlineWith inline
No captureOne static method (reused)Full inlining, no call
1 variable captureAnonymous class (one object)Full inlining, no object
N variables captureAnonymous class with N fieldsFull inlining, no object
RecursiveNormal callinline is prohibited

According to Android Performance Patterns (Google, 2024), in applications with intensive collection usage (filtering, sorting, grouping) inline functions reduce allocations by 25–35%. The effect is especially noticeable in Jetpack Compose, where each state change triggers recomposition with many lambdas.

Nonlocal return and limitations

A lambda in a regular function cannot return from the outer function — only a local return from the lambda itself (via return@label). In an inline function, the lambda is inlined into the calling function's body, so nonlocal return becomes possible: a return inside the lambda terminates the outer function.

kotlin
inline fun findFirst(
    items: List<Int>,
    predicate: (Int) -> Boolean
): Int {
    for (item in items) {
        if (predicate(item)) {
            return item
        }
    }
    return -1
}

fun processNumbers() {
    val numbers = listOf(1, 2, 3)
    val firstEven = findFirst(numbers) { it % 2 == 0 }
    // return in lambda would return null from processNumbers()
}

Nonlocal return is convenient for early termination but can lead to errors. If the lambda is used in a non-local context (stored in a variable), a nonlocal return will cause a RuntimeException. The Kotlin compiler issues a warning when attempting such storage.

noinline and crossinline: controlling inlining

When a function has multiple lambda parameters, sometimes you need to inline only some of them. noinline is used for this — it prevents inlining of a specific lambda parameter, leaving it as a regular Function object.

The crossinline modifier solves the opposite problem: the lambda is inlined, but nonlocal return is prohibited. This is needed when the lambda is used inside another lambda or in a context where return is not allowed (for example, passed to a Runnable).

kotlin
inline fun processWithCallback(
    data: String,
    crossinline onSuccess: (String) -> Unit,
    noinline onError: (Exception) -> Unit
) {
    try {
        val result = process(data)
        onSuccess(result)
    } catch (e: Exception) {
        onError(e)
    }
}

// noinline: onError can be stored in a variable or passed elsewhere
val errorHandler = { e: Exception -> log(e.message) }
processWithCallback("input", { println(it) }, errorHandler)

In the example, onSuccess is marked as crossinline — it will be inlined, but return cannot be used inside it. onError is marked as noinline — it is not inlined, so it can be passed as an object, stored in a class field, or used as a listener.

Inline function limitations and recommendations

Inline functions have limitations. Recursive inline functions are prohibited — the compiler will return an error. Inline functions cannot have private or internal visibility if declared in another module, but this is a visibility limitation, not related to the inlining mechanism itself.

The bytecode size grows with each inline function call, since the body is copied. According to Kotlin Coding Conventions (JetBrains, 2025), it is recommended to use inline only for functions up to 10–15 lines. For large functions, the benefit from inlining lambdas may be negated by the APK size increase (critical in Android due to the 64K method limit).

kotlin
// Recommended practice
inline fun withLock(lock: Lock, action: () -> T): T {
    lock.lock()
    try {
        return action()
    } finally {
        lock.unlock()
    }
}

// Not recommended for large functions
inline fun largeComputation(...) { // bad — body >50 lines
    // more than 50 lines — better to extract into a regular function
}

Public inline functions in libraries require caution: if the body of an inline function changes, all clients must be recompiled. JetBrains recommends using @PublishedApi internal for members called from inline functions to maintain compatibility within a module.

Frequently Asked Questions

Can inline extension function be created?

Yes, inline extension function works without restrictions. For example: inline fun String.transform(block: (Char) -> Char): String. Extension does not affect the ability to inline — the compiler handles it the same way as a regular inline function.

When does inline NOT provide benefits?

If the function does not accept lambda parameters — inline provides no advantage. The Kotlin compiler issues a warning: “Expected performance impact from inlining is insignificant. Inlining works best for functions with parameters of functional types.” Also, inline is harmful for large functions due to bytecode growth.

How is inline different from @JvmInline (value class)?

inline — a function modifier that inlines the function body at the call site. @JvmInline (value class) — a mechanism for wrapper classes that are replaced by their value at compile time. Different concepts: inline optimizes calls, value class optimizes data representation.

Can inline be used with suspend functions?

No, suspend functions cannot be inline because they compile into a state machine with Continuation. However, an inline function can accept a suspend lambda as a parameter with crossinline. This is often used in coroutines: inline fun launch(block: suspend CoroutineScope.() -> Unit).

Does inline affect debugging?

Yes, inline functions complicate debugging because the function body is not called but inlined at the call site. Stacktraces become longer, breakpoints work but may show unexpected positions. JetBrains recommends debugging without inline and enabling it only in release builds.

Summary

  • inline function — inlines the function body at the call site, eliminating lambda overhead
  • Nonlocal return — return from a lambda terminates the outer function (only possible with inline)
  • noinline — prevents inlining of a specific lambda parameter
  • crossinline — allows inlining but prohibits nonlocal return
  • Recursive functions cannot be inline — the compiler returns an error
  • Bytecode size grows — use inline for functions up to 10–15 lines
  • Optimal usage — higher-order functions with lambda parameters, synchronization blocks, scope functions (let, apply, also, run)

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also