tezvyn:

Rust's `panic!`: When to Crash Your Program Intentionally

AI-drafted, machine-checkedSource: doc.rust-lang.orgadvanced

Rust's `panic!` is an emergency stop for unrecoverable bugs, intentionally crashing the current thread. It's for impossible states where continuing is dangerous, not for recoverable errors like failed I/O—use `Result` for that.

WHY IT EXISTS: To provide a clear, immediate way to stop a program when it enters an invalid state due to a bug. It prevents the program from continuing with corrupt data, which could lead to worse, silent failures. It's for errors the programmer believes should be impossible.

THE MENTAL MODEL: Think of panic! as pulling the emergency brake on a train. It's a drastic, last-resort action for when something has gone fundamentally wrong and continuing poses a greater risk. It's not for routine stops or expected delays (like a red signal), which are analogous to the Result type. A panic signals a bug in the system itself, not an expected failure.

HOW IT WORKS: When panic! is called, it causes the current thread to panic. By default, this means the thread unwinds its stack, running destructors for all objects on the stack to clean up resources. It then prints a panic message, including the file and line number, to standard error. If the main thread panics, the entire program terminates with a non-zero exit code (101). This behavior can be changed to abort immediately without unwinding, or customized using std::panic::set_hook.

WHEN TO USE IT: Use panic! when a contract or invariant in your code is violated. Three key places are: first, in examples and tests to assert correctness; second, for unrecoverable logic errors where unwrap() is a conscious choice; third, when a state is reached that your program's logic should make impossible. It signals that a programmer's assumption was wrong.

WHEN NOT TO USE IT: Do not use panic! for expected, recoverable errors. A user providing invalid input, a file not being found, or a network request failing are all anticipated runtime failures. These should be handled by returning a Result<T, E>, allowing the calling code to decide how to respond without crashing the program. Overusing panic! makes for brittle, unresilient software.

ONE CANONICAL EXAMPLE: A function that requires a non-empty slice might panic if given an empty one, because its logic depends on at least one element being present. fn get_first(items: &[i32]) -> &i32 { if items.is_empty() { panic!("get_first called with an empty slice!"); } &items[0] } Calling get_first(&[]) would trigger the panic, as the function's core contract was violated.

Read the original → doc.rust-lang.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.