beps/docs/proposals/BEP-001-exceptions/legacy-ignore/context/rust.md
Rust uses the Result<T, E> enum (Sum Type) to represent success or failure. This forces the caller to handle the error (or explicitly ignore it) at compile time.
enum Result<T, E> {
Ok(T),
Err(E),
}
?Rust combines explicit values with ergonomic propagation. The ? operator is syntax sugar for "unwrap or return early".
fn read_config() -> Result<Config, io::Error> {
let mut file = File::open("config.toml")?; // Returns Err(io::Error) immediately if failed
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(parse(contents))
}
DX Pros:
? removes the if err != nil boilerplate while keeping the "early return" semantics visible.File::open(path).and_then(|f| ...)DX Cons:
? only works if the error type matches the function's return error type (or can be converted via From). This leads to "error soup" where you need a common error enum or a boxed trait object.thiserror vs anyhowRust's error handling splits into two main use cases:
Libraries (thiserror):
Libraries must export precise error types so callers can handle specific cases. thiserror derives the Error trait for enums.
#[derive(thiserror::Error, Debug)]
pub enum DataStoreError {
#[error("data store disconnected")]
Disconnect(#[from] io::Error),
#[error("the data for key `{0}` is not available")]
Redaction(String),
}
Applications (anyhow):
Apps usually just want to report errors. anyhow::Result<T> is a wrapper around Box<dyn Error + Send + Sync> with easy context attachment.
fn main() -> anyhow::Result<()> {
let config = read_config().context("failed to read configuration")?;
Ok(())
}
Tradeoff: Result is a value.
Result layout (e.g., Option<Box<T>> is a single pointer, null=None).Result generate code for every T and E, potentially increasing binary size.Rust strictly separates:
Result: Recoverable errors (file not found, network timeout).panic!: Unrecoverable bugs (index out of bounds). Unwinds the stack (or aborts).catch_unwind, which is discouraged for logic control).Tradeoff: match must cover all cases.
?).Rust provides the safety of checked exceptions with the ergonomics of unchecked exceptions (via ?) and the performance of C return codes. The learning curve lies in managing error types and conversions.