Option<T> and Result<T, E> in Depth

Avoiding Unnecessary Panics

Production Rust code treats panics (unwrap(), expect(), out-of-bounds v[i], unchecked a / b, and mid-character &s[a..b]) as bugs or unrecoverable invariant violations—never as normal control flow for handling bad user input, network failures, or edge-case data.

Non-Panicking Replacements for Common Panicking Operations

Panicking Operation Non-Panicking Replacement Return Type
opt.unwrap() / res.unwrap() opt? / res?, if let, let ... else, or .unwrap_or_default() Propagates or handles None / Err
slice[i] / vec[i] slice.get(i) / slice.get_mut(i) Option<&T> / Option<&mut T>
slice[0] / slice[slice.len() - 1] slice.first() / slice.last() Option<&T>
&s[start..end] (string slice) s.get(start..end) or s.split_at_checked(mid) Option<&str> / Option<(&str, &str)>
vec.remove(i) / vec.split_off(i) Check i < vec.len() or use vec.pop() Option<T>
a + b, a - b, a * b (integer overflow) a.checked_add(b), a.saturating_sub(b) Option<T> or clamped T
a / b (division by zero or MIN / -1) a.checked_div(b) Option<T>

Early Return Guards with let ... else

When a function cannot use ? (for example, when it returns () or needs to log a warning and continue in a loop), the let Pattern = expr else { diverge } statement unwraps Some(v) or Ok(v) into the outer scope without indenting the rest of the function or calling .unwrap():

fn process_metric_lines(lines: &[&str]) -> Vec<(&str, u64)> {
    let mut valid = Vec::new();

    for &line in lines {
        // Unwraps `Some((name, raw_val))` or skips malformed lines cleanly:
        let Some((name, raw_val)) = line.split_once(':') else {
            continue;
        };

        // Unwraps `Ok(value)` or skips unparseable numbers cleanly:
        let Ok(value) = raw_val.trim().parse::<u64>() else {
            continue;
        };

        valid.push((name.trim(), value));
    }

    valid
}

fn main() {
    let input = [
        "cpu_load: 72",
        "malformed_line_without_colon",
        "mem_mb: not_a_number",
        "disk_gb: 512",
    ];

    println!("Valid metrics: {:?}", process_metric_lines(&input));
}
Valid metrics: [("cpu_load", 72), ("disk_gb", 512)]

Enforcing Panic-Free Code with Clippy Lints

In libraries or high-reliability services, enable Clippy's restriction lints to reject .unwrap(), .expect(), and direct indexing at compile time:

#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![deny(clippy::indexing_slicing)]

When an invariant truly is guaranteed by surrounding logic (such as a hardcoded valid regex or a just-checked condition), prefer .expect("reason why this invariant holds") over bare .unwrap(), phrasing the message as an assertion explanation rather than a generic error message.