# What Does the Kotlin Elvis Operator Do? A Deep Dive into ?: Syntax

> Understand the Kotlin Elvis operator ?: Learn how it handles null values by returning the left operand if non-null, or the right operand if null. Master this concise syntax.

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

---

**The Kotlin Elvis operator (`?:`) is a null-coalescing operator that returns the left-hand expression if it is non-null, or evaluates and returns the right-hand expression if the left-hand side is null.**

The Elvis operator is a cornerstone of Kotlin's null-safety system, providing a concise way to handle nullable values without verbose if-null checks. As implemented in the JetBrains/kotlin compiler, this operator compiles down to efficient bytecode while maintaining readable syntax. Understanding how the kotlin elvis operator works at both the source and compiler level helps developers write more idiomatic null-safe code.

## Kotlin Elvis Operator Syntax and Basic Usage

The Elvis operator follows the pattern `left ?: right`. If the left operand is non-null, the operator returns that value immediately. If the left operand evaluates to null, the right operand is evaluated and its result is returned instead.

```kotlin
val name: String? = getUserName()
val display = name ?: "Anonymous"

```

In this example, if `name` contains a non-null string, `display` receives that value. If `name` is null, the string `"Anonymous"` is assigned instead.

## How the Kotlin Compiler Implements the Elvis Operator

The implementation of the kotlin elvis operator spans multiple phases of the Kotlin compiler pipeline, from parsing through intermediate representation (IR) generation to JVM bytecode emission.

### Parsing the ?: Token

In [`compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt`](https://github.com/JetBrains/kotlin/blob/main/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt), the parser identifies `?:` as a binary operator with the special origin `IrStatementOrigin.ELVIS`. This origin marker signals to subsequent compiler phases that this node requires specific null-coalescing logic rather than standard binary operator handling.

### IR Generation with generateElvis

The `generateElvis` function in [`OperatorExpressionGenerator.kt`](https://github.com/JetBrains/kotlin/blob/main/OperatorExpressionGenerator.kt) creates an `IrWhen` expression that represents the runtime null-check. This intermediate representation captures the conditional logic—checking if the left side is null—before platform-specific lowering occurs.

```kotlin
// Simplified view from OperatorExpressionGenerator.kt
private fun generateElvis(expression: KtBinaryExpression): IrExpression {
    val resultType = getResultTypeForElvis(expression).toIrType()
    // Creates an IrWhen expression checking lhs != null
}

```

### JVM Backend Optimization

The JVM backend optimizes Elvis chains through [`compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmSafeCallChainFoldingLowering.kt`](https://github.com/JetBrains/kotlin/blob/main/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmSafeCallChainFoldingLowering.kt). This lowering phase extracts `ElvisInfo` structures via the `parseElvis` function and rewrites the IR tree using `foldElvis`. The optimization converts the operation into efficient conditional jumps, eliminating temporary variables where possible.

### Bytecode Generation

The final bytecode generation phase translates the lowered IR into JVM instructions using an `if-null-goto` pattern. This produces compact bytecode that maintains the exact semantics of the original kotlin elvis operator while ensuring minimal runtime overhead.

## Practical Kotlin Elvis Operator Examples

The Elvis operator handles complex scenarios including nested safe calls, side effects, and type conversions.

```kotlin
// Simple Elvis usage with fallback value
val name: String? = getUserName()
val display = name ?: "Anonymous"

// Elvis with side effects on the right side
val result = computeExpensiveValue() ?: fallback()
// `fallback()` only executes if `computeExpensiveValue()` returns null

// Elvis in a chain of safe calls
val length = (user?.profile?.bio?.length) ?: 0
// Returns the bio length if the entire chain is non-null; otherwise 0

// Using Elvis to assign a non-null value to a mutable variable
var cached: Data? = null
cached = cached ?: loadFromNetwork()

```

## Key Source Files in the Kotlin Compiler

Understanding the implementation requires examining specific files in the JetBrains/kotlin repository:

- **[`compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt`](https://github.com/JetBrains/kotlin/blob/main/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt)** – Parses `?:` as `IrStatementOrigin.ELVIS` and generates the initial `IrWhen` expression via `generateElvis`.

- **[`compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmSafeCallChainFoldingLowering.kt`](https://github.com/JetBrains/kotlin/blob/main/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmSafeCallChainFoldingLowering.kt)** – Optimizes Elvis chains for the JVM by extracting `ElvisInfo` and applying `parseElvis` and `foldElvis` transformations.

- **[`compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt`](https://github.com/JetBrains/kotlin/blob/main/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt)** – Contains feature flags such as `ElvisInferenceImprovementsIn21` that affect type inference for Elvis expressions in Kotlin 2.1+.

- **[`compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/UselessElvisCallChecker.kt`](https://github.com/JetBrains/kotlin/blob/main/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/UselessElvisCallChecker.kt)** – Provides diagnostics that warn when the left side of `?:` is already non-null, detecting redundant Elvis usage.

## Summary

- The kotlin elvis operator (`?:`) provides null-coalescing functionality, returning the left operand if non-null or the right operand if the left is null.
- The compiler parses `?:` as `IrStatementOrigin.ELVIS` in [`OperatorExpressionGenerator.kt`](https://github.com/JetBrains/kotlin/blob/main/OperatorExpressionGenerator.kt) and generates an `IrWhen` expression via `generateElvis`.
- JVM backend optimization in [`JvmSafeCallChainFoldingLowering.kt`](https://github.com/JetBrains/kotlin/blob/main/JvmSafeCallChainFoldingLowering.kt) folds Elvis chains into efficient `if-null-goto` bytecode patterns using `ElvisInfo` structures.
- The operator supports complex expressions, conditional side effects on the right-hand side, and nested safe calls while maintaining type safety through smart inference improvements in Kotlin 2.1+.

## Frequently Asked Questions

### What is the difference between the Kotlin Elvis operator and the safe call operator?

The safe call operator (`?.`) returns null if the left side is null and does not evaluate the right side, while the Elvis operator (`?:`) provides a fallback value when the left side is null. You often use them together: `user?.name ?: "Unknown"` first safely accesses the name, then provides a default if either the user or the name is null.

### Can the right-hand side of the Elvis operator have side effects?

Yes, the right-hand side expression is evaluated only when the left-hand side is null, so any function calls, assignments, or other side effects on the right execute conditionally. This makes the Elvis operator useful for lazy initialization patterns like `cached = cached ?: loadFromNetwork()`, where `loadFromNetwork()` only runs when `cached` is null.

### Is the Elvis operator in Kotlin the same as the null-coalescing operator in PHP or C#?

Yes, Kotlin's `?:` serves the same purpose as the `??` operator in PHP and C#, providing a concise way to specify default values for nullable expressions. All three operators evaluate the left operand first and return the right operand only if the left is null, making them functionally equivalent despite the different syntax.

### How does Kotlin handle type inference with the Elvis operator?

The compiler computes a common supertype between the left and right operands to determine the result type. In Kotlin 2.1 and later, improvements via the `ElvisInferenceImprovementsIn21` feature flag provide smarter inference for complex Elvis chains, allowing more precise type resolution when combining nullable and non-null expressions.