Option & Result as Enums
Option<T> models presence or absence. Result<T, E> models success or recoverable failure. Together they replace null and exceptions.
Search across all documentation pages
Option<T> models presence or absence. Result<T, E> models success or recoverable failure. Together they replace null and exceptions.
fn divide(a: f64, b: f64) -> Option<f64> {
if b == 0.0 { None } else { Some(a / b) }
}
fn read_port(s: &str) -> Result<u16, std::num::ParseIntError> {
s.parse()
}
fn main() {
println!("{:?} {:?}", divide(10.0, 2.0), read_port("8080"));
}When to reach for this: Any optional value (Option) and any fallible operation (Result).
fn first_line(path: &str) -> Result<Option<String>, std::io::Error> {
let mut lines = std::fs::read_to_string(path)?.lines();
Ok(lines.next().map(|s| s.to_string()))
}
fn main() {
match first_line("Cargo.toml") {
Ok(Some(l)) => println!("{l}"),
Ok(None) => println!("empty"),
Err(e) => eprintln!("{e}"),
}
}What this demonstrates:
Result for I/O failureOption inside Ok for empty file? propagates io::Errorenum Option<T> { None, Some(T) }
enum Result<T, E> { Ok(T), Err(E) }Option -> Result: ok_or, ok_or_elseResult -> Option: ok, err? on Result in functions returning ResultOption is not error handlingUse Result when caller needs failure reason. Option for legitimately missing data.
unwrap in library code - Panics caller. Fix: Return Result or Option.None for errors - Loses context. Fix: Result with error type.? on Option in Result fn - Needs From or ok_or. Fix: ok_or(MyError::Missing)? or ? in Option returning fn only.Result - Allocation cost. Fix: Box<dyn Error> or thiserror enums in apps.? - Nested match hell. Fix: ? and combinators.| Alternative | Use When | Don't Use When |
|---|---|---|
panic! | Programmer bug, impossible branch | Expected failures |
| Custom enum | Closed error set in domain | Result suffices |
anyhow in binaries | Flexible errors | Public library API |
| Sentinel values | Never in safe Rust APIs | - |
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.
Reviewed by Chris St. John·Last updated Jul 16, 2026