skip to content

Nothing — the Bottom Type

Nothing has no instances and is a subtype of every type, which is how throw, TODO(), and error() type-check in any position. It is also why val x = if (c) 1 else throw ... still infers Int, a favorite interview puzzle.

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

questions

5

What is kotlin.Nothing, and how does it differ from Unit?

level: juniorimportance: must knowfreq 70%

answer

  1. Unit = one value (void); Nothing = zero values
  2. Unit always returns; Nothing never returns
  3. TODO()/error()/throw produce Nothing
  4. Nothing is bottom; Unit is near top
  5. Code after a Nothing call is unreachable

basics

~10 s

Nothing is a type with no values at all; it marks code that never returns normally, like throwing an exception. Unit means a function returns but gives back nothing useful, like void.

solid answer

~40 s

Nothing is Kotlin's uninhabited bottom type: it has zero instances, so no value can ever be of type Nothing. It is the declared return type of functions that never complete normally, e.g. expressions that throw or call TODO(). Unit is the opposite: it is inhabited by exactly one value, the Unit object, and is the return type of functions that complete but produce no meaningful result (Java's void). A function returning Unit always returns; a function returning Nothing never returns. Because Nothing is a subtype of every type, throw is an expression usable anywhere a value is expected (e.g. val x = something ?: throw ...). Unit is a regular type that sits near the top, not a subtype of everything.

code

kotlin · 7 lines
kotlin
fun unitFn(): Unit { println("done") }       // always returns
fun nothingFn(): Nothing { throw IllegalStateException() } // never returns

fun demo(x: Int) {
    val r = if (x > 0) x else nothingFn() // else branch is Nothing -> r: Int
    println(r)
}

go deeper

for a junior

States Nothing has no values and marks never-returning code; contrasts with Unit as void.

for a middle

Names TODO()/error()/throw as Nothing, explains 'always returns vs never returns' and unreachable code.

for a senior

Connects Nothing being the bottom type to smart-casts and using throw/return as expressions.

for a principal

Frames Unit vs Nothing in lattice terms and discusses how reachability analysis is driven by Nothing return types.

## Two opposite "empty-ish" types Kotlin has two types that both feel like "nothing useful is produced," but they are conceptually opposite. ### Unit — the no-value type - **Unit** is a real type with **exactly one value**, the singleton object also written `Unit`. - It is the equivalent of Java's `void`. A function declared to return `Unit` (or with no explicit return type for a block body) **always returns normally** — it just has nothing interesting to hand back. - Example: `fun log(msg: String): Unit { println(msg) }`. The `: Unit` is optional and usually omitted. ### Nothing — the bottom type - **Nothing** is the **uninhabited** type: it has **zero values**. You can never create or hold a `Nothing`. - A function whose return type is `Nothing` **never returns normally** — it must throw, loop forever, or exit the process. - Standard library examples: `TODO()`, `error("...")`, and `kotlin.system.exitProcess()` all return `Nothing`. - Because there are no values, the compiler treats the line after such a call as **unreachable**. ### Why the difference matters A caller of a `Unit` function continues afterward. A caller of a `Nothing` function does **not** — control never comes back. The compiler uses this for **reachability** and **smart-cast** analysis. ```kotlin fun parse(input: String?): Int { val s = input ?: return -1 // ok: return has type Nothing val n = s.toIntOrNull() ?: error("bad: $s") // error() : Nothing return n // s and n smart-cast to non-null } ``` ### Position in the type lattice - `Unit` is just an ordinary type sitting near the top of the hierarchy (a subtype of `Any`). - `Nothing` is the **bottom** of the lattice: a subtype of **every** type, so a `Nothing`-valued expression like `throw e` fits in any slot.

  • Can you declare a variable of type Nothing?
    You can write `val x: Nothing`, but you can never initialize it with a real value (only with an expression that itself never returns, like `throw`), so in practice you cannot hold one.
  • Why is `return` an expression of type Nothing?
    Because executing `return` transfers control out of the function, the surrounding expression never yields a value, so its type is Nothing — usable in `?:`, `if`, etc.

Unit is an empty gift box you still hand over; Nothing is a gift that never arrives because you walked off a cliff first.

saying these in an interview costs you the question

  • Saying Nothing and Unit are the same or interchangeable
  • Claiming Unit has no value (it has exactly one)
  • Thinking you can create a Nothing instance
  • Saying a Nothing function returns null
  • Confusing Nothing with Java void

context

open as a page

Why is Nothing a subtype of every type, and what does that enable in everyday Kotlin code?

level: middleimportance: must knowfreq 60%

basics

~20 s

Nothing sits at the bottom of Kotlin's type hierarchy, so it counts as every type at once. That lets a throw or a never-returning call be used wherever any value is expected, like on the right of the elvis operator.

open as a page

How do you declare a function that never returns, and what compiler behaviors does a Nothing return type unlock (TODO, error, require)?

level: middleimportance: should knowfreq 55%

basics

~20 s

Give the function the return type Nothing and make sure every path throws or loops forever. Then the compiler knows code after a call to it is dead and can smart-cast variables, the way TODO() and error() do.

open as a page

What is the type of the literal `null`, and how do Nothing and Nothing? behave with generics like emptyList()?

level: seniorimportance: should knowfreq 45%

basics

~10 s

The bare null literal has type Nothing?, the nullable bottom type whose only value is null. Because Nothing is below everything, an empty list typed List<Nothing> can stand in for a list of anything.

open as a page

How does the compiler use Nothing-returning expressions in control-flow / smart-cast analysis, and where can this break down?

level: seniorimportance: nice to knowfreq 35%

basics

~20 s

When a branch ends in something that never returns, the compiler knows execution can't continue down that path, so afterward it can treat variables as non-null or narrowed. This breaks if the variable could change between the check and use.

open as a page