14.1 Introduction to Option Types

In many programming scenarios, values can be absent. Rust addresses this by making ‘absence’ explicit at the type level. Rather than letting you ignore a missing value until it potentially causes a runtime error, Rust forces you to consider both presence and absence at compile time.

14.1.1 The Option Enum

Rust’s standard library defines Option<T> as:

#![allow(unused)]
fn main() {
enum Option<T> {
    Some(T),
    None,
}
}
  • Some(T): Indicates a valid value of type T.
  • None: Signifies that no value is present.

These variants are in the Rust prelude, so you do not need to bring them into scope manually. You can simply write:

#![allow(unused)]
fn main() {
let value: Option<i32> = Some(42);
let no_value: Option<i32> = None;
}

Type Inference and None
When you write Some(...), Rust usually infers the type automatically. However, if you only write None, the compiler may need a hint:

#![allow(unused)]
fn main() {
let missing = None; // Error: Rust doesn't know which type you need here
}

To fix this, you specify the type:

#![allow(unused)]
fn main() {
let missing: Option<u32> = None;
}

14.1.2 Why Use an Option Type?

Many everyday programming tasks require the ability to represent ‘no value’:

  • Searching a collection may fail to find the target.
  • A configuration file might omit certain settings.
  • A database query can return zero results.
  • Iterators naturally end and have no further items to return.

By using Option<T>, Rust requires you to handle both the ‘found’ (Some) and ‘not found’ (None) cases, preventing you from accidentally ignoring missing data. This is a significant departure from C, where NULL or a sentinel value might be used without always forcing an explicit check.

14.1.3 Tony Hoare and the ‘Billion-Dollar Mistake’

Tony Hoare introduced the concept of the null reference in 1965. He later described it as his ‘billion-dollar mistake’ because of the vast expense and bugs caused by dereferencing NULL in languages like C. Rust tackles this head-on with Option<T>, making the absence of a value a deliberate part of the type system.

14.1.4 Null Pointers Versus Option

In C, forgetting to check for NULL before dereferencing a pointer can lead to crashes or undefined behavior. Rust solves this by requiring you to acknowledge the possibility of absence through Option<T>. You cannot turn an Option<T> into a T without handling the None case, ensuring that ‘null pointer dereferences’ are caught at compile time, not at runtime.