# The Nothing Type

A Nothing return type indicates a function that never returns

This is usually a function that always throws an exception.

Here’s a function that produces an infinite loop (avoid these)—because it never returns, its return type is Nothing:

// NothingType/InfiniteLoop.kt
package nothingtype

fun infinite(): Nothing {
  while (true) {}
}

Nothing is a built-in Kotlin type with no instances.

A practical example is the built-in TODO(), which has a return type of Nothing and throws NotImplementedError:

// NothingType/Todo.kt
package nothingtype
import atomictest.*

fun later(s: String): String = TODO("later()")

fun later2(s: String): Int = TODO()

fun main() {
  capture {
    later("Hello")
  } eq "NotImplementedError: " +
    "An operation is not implemented: later()"
  capture {
    later2("Hello!")
  } eq "NotImplementedError: " +
    "An operation is not implemented."
}

Both later() and later2() return non-Nothing types even though TODO() returns Nothing. Nothing is compatible with any type.

later() and later2() compile successfully. If you call either one, an exception reminds you to write implementations. TODO() is a useful tool for “sketching” a code framework to verify that everything fits together before filling in the details.

In the following, fail() always throws an Exception so it returns Nothing. Notice that a call to fail() is more readable and compact than explicitly throwing an exception:

// NothingType/Fail.kt
package nothingtype
import atomictest.*

fun fail(i: Int): Nothing =
  throw Exception("fail($i)")

fun main() {
  capture {
    fail(1)
  } eq "Exception: fail(1)"
  capture {
    fail(2)
  } eq "Exception: fail(2)"
}

fail() allows you to easily change the error-handling strategy. For example, you can change the exception type or log an additional message before throwing an exception.

This throws a BadData exception if the argument is not a String:

// NothingType/CheckObject.kt
package nothingtype
import atomictest.*

class BadData(m: String) : Exception(m)

fun checkObject(obj: Any?): String =
  if (obj is String)
    obj
  else
    throw BadData("Needs String, got $obj")

fun test(checkObj: (obj: Any?) -> String) {
  checkObj("abc") eq "abc"
  capture {
    checkObj(null)
  } eq "BadData: Needs String, got null"
  capture {
    checkObj(123)
  } eq "BadData: Needs String, got 123"
}

fun main() {
  test(::checkObject)
}

checkObject()’s return type is the return type of the if expression. Kotlin treats a throw as type Nothing, and Nothing can be assigned to any type. In checkObject(), String takes priority over Nothing, so the type of the if expression is String.

We can rewrite checkObject() using a [safe cast and an Elvis operator](javascript:void(0)). checkObject2() casts obj to a String if it can be cast, otherwise it throws an exception:

// NothingType/CheckObject2.kt
package nothingtype

fun failWithBadData(obj: Any?): Nothing =
  throw BadData("Needs String, got $obj")

fun checkObject2(obj: Any?): String =
  (obj as? String) ?: failWithBadData(obj)

fun main() {
  test(::checkObject2)
}

When given a plain null with no additional type information, the compiler infers a nullable Nothing:

// NothingType/ListOfNothing.kt
import atomictest.eq

fun main() {
  val none: Nothing? = null

  var nullableString: String? = null    // [1]
  nullableString = "abc"
  nullableString = none                 // [2]
  nullableString eq null

  val nullableInt: Int? = none          // [3]
  nullableInt eq null

  val listNone: List<Nothing?> = listOf(null)
  val ints: List<Int?> = listOf(null)   // [4]
  ints eq listNone
}

You can assign both null and none to a var or val of a nullable type, such as nullableString or nullableInt. This is allowed because the type of both null and none is Nothing? (nullable Nothing). In the same way that an expression of the Nothing type (for example, fail()) can be interpreted as “any type,” an expression of the Nothing? type, such as null, can be interpreted as “any nullable type.” Assignments to different nullable types are shown in lines [1], [2] and [3].

listNone is initialized with a List containing only the null value. The compiler infers this to be List<Nothing?>. For this reason, you must explicitly specify the element type ([4]) that you want to store in the List when you initialize it with only null.

Exercises and solutions can be found at www.AtomicKotlin.com.