Rust splits failures into two kinds, and the distinction shapes everything: unrecoverable errors that should stop the program, and recoverable errors that callers can handle. This lesson is the first kind: panic!.
When the program should just stop
A panic! means 'something is so wrong that continuing is meaningless.' It unwinds the stack, runs destructors, and aborts the thread. You reach for it on bugs that should never happen — a violated invariant, an index that math guarantees is in-bounds, a 'this case is truly impossible' branch.
unwrap and expect
.unwrap() on an Option or Result panics if it's None/Err. .expect("message") does the same but with your message in the panic — strictly better, because the message tells future-you why you were sure it couldn't fail. Both are panics in disguise: use them when a failure genuinely means a bug, not an expected condition.
Result. A failed invariant your own code should have upheld is a bug — panic, and fix the code. Confusing the two gives you either crashes-in-production or error-handling theater.panic isn't an exception
Don't reach for panic! as a throw-and-catch mechanism. While you can catch an unwinding panic, it's meant for genuinely-unrecoverable situations, not control flow. Recoverable errors flow through Result values, which the rest of this track is about.