# How to Use a For Loop in Kotlin: Syntax, Ranges, and Compiler Internals

> Master Kotlin for loops with syntax examples, range usage, and compiler insights. Learn to iterate efficiently over collections, arrays, and more in your code.

- Repository: [JetBrains/kotlin](https://github.com/jetbrains/kotlin)
- Tags: how-to-guide
- Published: 2026-02-12

---

**Use `for (item in iterable) { ... }` to iterate over any object that provides an `iterator()` operator, including collections, numeric ranges, and arrays.**

Kotlin’s `for` loop is a high-level construct that abstracts iteration behind a unified, readable syntax. According to the JetBrains/kotlin source code, the compiler transforms this syntax into optimized platform-specific code through a multi-stage lowering pipeline involving PSI parsing, FIR-to-IR conversion, and backend-specific code generation.

## Basic For Loop Syntax and Iterator Protocol

### The `for (variable in expression)` Pattern

Every Kotlin for loop follows the pattern `for (item in collection) { ... }`. Unlike C-style for loops, Kotlin’s version iterates over anything that provides an **iterator**. The compiler requires the expression to have a member or extension function `iterator()` that returns an object with `hasNext()` and `next()` methods.

```kotlin
val fruits = listOf("apple", "banana", "cherry")
for (fruit in fruits) {
    println(fruit)
}

```

### Built-in Iterable Types

Kotlin’s standard library provides iterators for common types without requiring explicit imports:

- **Collections**: `List`, `Set`, and `Map` (via `entries`, `keys`, or `values`)
- **Ranges**: `IntRange`, `LongRange`, and `CharRange`
- **Arrays**: `Array<T>`, `IntArray`, `CharArray`, and primitive variants
- **Strings**: Iterates over `Char` sequences

## Iterating Over Numeric Ranges and Progressions

### Inclusive and Half-Open Ranges

Use the `..` operator for inclusive ranges or `until` for half-open ranges that exclude the end value.

```kotlin
// Inclusive range: prints 1, 2, 3, 4, 5
for (i in 1..5) {
    println(i)
}

// Half-open range: prints 0, 1, 2, 3, 4
for (i in 0 until 5) {
    println(i)
}

```

### Reverse Iteration and Custom Steps

Use `downTo` for reverse iteration and `step` to specify increments other than 1. Under the hood, the compiler generates a **progression header** via [`ProgressionLoopHeader.kt`](https://github.com/JetBrains/kotlin/blob/main/ProgressionLoopHeader.kt) and [`DefaultProgressionHandler.kt`](https://github.com/JetBrains/kotlin/blob/main/DefaultProgressionHandler.kt) to track start, end, step, and direction values.

```kotlin
// Reverse with step: prints 10, 8, 6, 4, 2, 0
for (i in 10 downTo 0 step 2) {
    println(i)
}

```

## Advanced Iteration Patterns

### Index-Based Iteration with `indices`

Access array or list indices using the `indices` property, which returns an `IntRange` that the compiler optimizes into a simple counter loop.

```kotlin
val values = arrayOf(10, 20, 30)
for (i in values.indices) {
    println("Index $i = ${values[i]}")
}

```

### Destructuring in Loop Variables

When iterating over `Map` entries or `Pair` collections, use destructuring declarations to unpack values directly in the loop header.

```kotlin
val map = mapOf("a" to 1, "b" to 2)
for ((key, value) in map) {
    println("$key -> $value")
}

```

### Custom Iterator Implementation

Any class can be used in a for loop by implementing the `iterator()` operator function.

```kotlin
class Counter(private val limit: Int) {
    operator fun iterator() = object : Iterator<Int> {
        var current = 0
        override fun hasNext() = current < limit
        override fun next() = current++
    }
}

for (i in Counter(3)) {
    println(i)  // Prints: 0, 1, 2
}

```

## Compiler Internals: How For Loops Are Transformed

The Kotlin compiler desugars for loops through several intermediate representations before generating bytecode or machine code. This architecture enables high-level syntax while producing efficient runtime performance.

### Parsing and PSI Representation

During the parsing phase, the source syntax `for (item in collection)` becomes a `KtForExpression` node in the Program Structure Interface (PSI) tree. This representation is defined in [`compiler/frontend.common-psi/src/org/jetbrains/kotlin/psi/KtForExpression.kt`](https://github.com/JetBrains/kotlin/blob/main/compiler/frontend.common-psi/src/org/jetbrains/kotlin/psi/KtForExpression.kt).

### FIR to IR Conversion

In the frontend intermediate representation (FIR), the loop is represented as `FirForLoopStatement` located at [`compiler/fir/ir/src/org/jetbrains/kotlin/fir/expressions/FirForLoopStatement.kt`](https://github.com/JetBrains/kotlin/blob/main/compiler/fir/ir/src/org/jetbrains/kotlin/fir/expressions/FirForLoopStatement.kt). When converting to the backend intermediate representation (IR), this becomes `IrForLoop`, preserving the high-level loop structure for subsequent optimization passes.

### IR Lowering with `ForLoopsLowering`

The critical transformation occurs in [`compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ForLoopsLowering.kt`](https://github.com/JetBrains/kotlin/blob/main/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ForLoopsLowering.kt). This pass **desugars** the high-level for loop into a while-style loop with an explicit iterator or numeric counter. For range-based loops, [`ProgressionLoopHeader.kt`](https://github.com/JetBrains/kotlin/blob/main/ProgressionLoopHeader.kt) calculates bounds and step values, while [`DefaultProgressionHandler.kt`](https://github.com/JetBrains/kotlin/blob/main/DefaultProgressionHandler.kt) generates the appropriate iterator logic for numeric progressions.

### Platform-Specific Code Generation

After IR lowering, platform-specific backends generate optimized code:

- **Kotlin/JVM**: [`ExpressionCodegen.kt`](https://github.com/JetBrains/kotlin/blob/main/ExpressionCodegen.kt) ([`compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt`](https://github.com/JetBrains/kotlin/blob/main/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt)) emits classic `for`-style integer loops (`int i = start; i <= end; i += step`) for ranges, avoiding iterator allocation overhead.
- **Kotlin/Native**: [`KonanBCEForLoopBodyTransformer.kt`](https://github.com/JetBrains/kotlin/blob/main/KonanBCEForLoopBodyTransformer.kt) ([`kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/KonanBCEForLoopBodyTransformer.kt`](https://github.com/JetBrains/kotlin/blob/main/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/KonanBCEForLoopBodyTransformer.kt)) applies bounds-check elimination optimizations to array iterations, generating direct pointer arithmetic where safe.

## Summary

- Kotlin for loops use the syntax `for (item in iterable)` and work with any object providing an `iterator()` operator, including custom classes.
- Numeric ranges support inclusive (`..`), half-open (`until`), reverse (`downTo`), and stepped (`step`) iteration patterns.
- The compiler optimizes range loops into efficient counter-based loops via `ProgressionLoopHeader` and `DefaultProgressionHandler`, eliminating iterator object allocation.
- Source files including [`KtForExpression.kt`](https://github.com/JetBrains/kotlin/blob/main/KtForExpression.kt), [`FirForLoopStatement.kt`](https://github.com/JetBrains/kotlin/blob/main/FirForLoopStatement.kt), and [`ForLoopsLowering.kt`](https://github.com/JetBrains/kotlin/blob/main/ForLoopsLowering.kt) define the transformation pipeline from high-level syntax to platform-specific bytecode or machine code.

## Frequently Asked Questions

### What's the difference between `for` and `forEach` in Kotlin?

Both construct loops, but `for` allows `break` and `continue` control flow and may generate tighter bytecode. According to [`ForLoopsLowering.kt`](https://github.com/JetBrains/kotlin/blob/main/ForLoopsLowering.kt), the compiler applies special optimizations to `for` loops over ranges and arrays that it cannot apply to `forEach` lambda invocations, potentially eliminating iterator allocation entirely.

### How does Kotlin optimize range-based for loops?

The compiler detects `IntRange`, `LongRange`, and `CharRange` iterations during the lowering phase in [`ForLoopsLowering.kt`](https://github.com/JetBrains/kotlin/blob/main/ForLoopsLowering.kt). It transforms these into simple while-loops with primitive counters via [`ProgressionLoopHeader.kt`](https://github.com/JetBrains/kotlin/blob/main/ProgressionLoopHeader.kt), generating bytecode comparable to Java’s `for (int i = 0; i < n; i++)` pattern rather than allocating iterator objects.

### Can I use a for loop without an iterator?

No. The Kotlin language specification requires the expression in a for loop to provide an `iterator()` function. To iterate by index without a collection iterator, use `withIndex()` or `indices`, both of which return objects that implement the iterator protocol required by the compiler.

### How do I iterate backwards with a custom step?

Use the `downTo` operator combined with `step`: `for (i in 10 downTo 0 step 2)`. The [`DefaultProgressionHandler.kt`](https://github.com/JetBrains/kotlin/blob/main/DefaultProgressionHandler.kt) recognizes this pattern and generates a `ProgressionLoopHeader` with a negative step value, enabling efficient reverse iteration without creating an intermediate reversed collection.