unwrap() and expect()
unwrap() and expect() are methods defined on both Option<T> and Result<T, E> that consume the wrapper and return the inner value T if present (Some(T) or Ok(T)), or immediately panic if the value is None or Err(E).
How unwrap() and expect() Work
Option<T> / Result<T, E>
├── Some(v) / Ok(v) ──> unwrap() or expect(msg) ──> returns v
└── None / Err(e) ──> unwrap() or expect(msg) ──> panics!
| Method | Receiver Type | On Some(v) / Ok(v) |
On None / Err(e) |
|---|---|---|---|
opt.unwrap() |
Option<T> |
Returns v |
Panics with "called Option::unwrap()on aNone value" |
opt.expect(msg) |
Option<T> |
Returns v |
Panics with "{msg}" |
res.unwrap() |
Result<T, E> (E: Debug) |
Returns v |
Panics with "called Result::unwrap()on anErr value: {e:?}" |
res.expect(msg) |
Result<T, E> (E: Debug) |
Returns v |
Panics with "{msg}: {e:?}" |
On Result<T, E>, both unwrap() and expect() require E: std::fmt::Debug so that the panic message can format the error value E.
Extracting Values When Success Is Present
fn main() {
let host: Option<&str> = Some("127.0.0.1");
let port: Result<u16, _> = "8080".parse();
let h = host.unwrap();
let p = port.expect("hardcoded port literal should be valid u16");
println!("Binding to {h}:{p}");
}
Binding to 127.0.0.1:8080
Panic Behavior on None and Err(e)
Calling unwrap() on Err(e) produces a generic panic message that shows the file and line number alongside the debug representation of e:
fn main() {
let count: i32 = "not_a_number".parse().unwrap();
println!("{count}");
}
thread 'main' panicked at src/main.rs:2:44:
called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }
Calling expect() attaches context explaining why the value was assumed to be valid, making crash diagnostics clearer:
fn main() {
let count: i32 = "not_a_number"
.parse()
.expect("WORKER_THREADS must be a valid integer");
println!("{count}");
}
thread 'main' panicked at src/main.rs:4:10:
WORKER_THREADS must be a valid integer: ParseIntError { kind: InvalidDigit }
unwrap_err() and expect_err() for Testing Failures
When testing that an operation fails, Result<T, E> provides the inverse methods unwrap_err() and expect_err(msg) (requiring T: Debug), which extract the error E from Err(e) or panic if the value is Ok(v):
fn main() {
let err = "99999".parse::<u8>().expect_err("99999 overflows u8");
println!("Caught expected parse error: {err}");
}
Caught expected parse error: number too large to fit in target type
Choosing Between expect(), unwrap(), and Non-Panicking Alternatives
| Scenario | Recommended Approach |
|---|---|
| Recoverable runtime failure (user input, network, files) | Propagate with ? or handle with match / let ... else |
| Missing value has a sensible fallback | Use unwrap_or(default) or unwrap_or_else(f) |
| Compile-time constant or invariant proven by surrounding code | Use expect("reason invariant holds") to document the proof |
| Unit tests and quick throwaway prototypes | unwrap() or expect() is concise and fails the test immediately |