The use of the Result type has become one of the key approaches to error handling in Rust. Historically, in many languages—such as C—errors were often signaled by special return values or global variables, which led to frequent mistakes when these signals were ignored. Rust took the route of explicit error typing with the enum Result<T, E>, making accidental error omission impossible—the compiler forces you to handle both branches (success and failure).
Problem: It was necessary to make error handling as safe and readable as possible, eliminate "hidden" errors, and increase code reliability without the need for exceptions.
Solution: Result<T, E> is an enumeration with two variants: Ok(T) for success and Err(E) for error. This forces you to explicitly handle errors, or explicitly ignore them using unwrap or expect panics. Additionally, the ? operator makes common error propagation patterns concise.
Example code:
use std::fs::File; use std::io::{self, Read}; fn read_file(path: &str) -> Result<String, io::Error> { let mut file = File::open(path)?; let mut contents = String::new(); file.read_to_string(&mut contents)?; Ok(contents) }
Key features:
? operator.Is it always possible to use the ? operator for automatic propagation of errors upwards?
No, only if the error type of the function matches the type of the expression on the right of ?. If the types are incompatible, you need to explicitly convert the error using the .map_err() method or your type.
Example code:
fn f() -> Result<(), String> { let _f = File::open("foo").map_err(|e| e.to_string())?; Ok(()) }
Can you leave the Result unchanged if you simply do not care about the errors?
No, the compiler will issue a warning or an error if a Result type is not handled. You either call .unwrap(), or explicitly call .ok()/.err()/let _ = ... or properly log the error.
What happens if you call .unwrap() on a Result with an error?
It will trigger a panic! and the program will terminate, usually leading to an abrupt exit. Therefore, unwrap() is only permissible when success is guaranteed.
let _ = ...;) without loggingA developer decided to read the config from a file and used unwrap() on the read result.
Pros:
Cons:
Errors while reading the config are logged and returned upwards through the call stack using Result + the ? operator.
Pros:
Cons: