The purpose of this post is to document the high-level structure and the relevant interfaces that come into play on the Rust side of this.
The actual mechanism of unwinding is a totally different matter (and one that I am not qualified to speak about).
+*Note:* This post describes panicking as of [this commit](https://github.com/rust-lang/rust/commit/7d761fe0462ba0f671a237d0bb35e3579b8ba0e8).
+Many of the interfaces described here are unstable internal details of libstd, and subject to change any time.
+
## High-level structure
When trying to figure out how panicking works by reading the code in libstd, one can easily get lost in the maze.
#### `rust_panic_with_hook`
-The key function that everything passes through is [`rust_panic_with_hook`](https://github.com/rust-lang/rust/blob/7d761fe0462ba0f671a237d0bb35e3579b8ba0e8/src/libstd/panicking.rs#L435-L437):
+The key function that almost everything passes through is [`rust_panic_with_hook`](https://github.com/rust-lang/rust/blob/7d761fe0462ba0f671a237d0bb35e3579b8ba0e8/src/libstd/panicking.rs#L435-L437):
{% highlight rust %}
fn rust_panic_with_hook(
payload: &mut dyn BoxMeUp,
#### libstd panicking entry points
-`rust_panic_with_hook` is a private function to `std::panicking`; the module provides three separate entry points on top of this central function:
+`rust_panic_with_hook` is a private function to `std::panicking`; the module provides three entry points on top of this central function, and one that circumvents it:
* the [default panic handler implementation](https://github.com/rust-lang/rust/blob/7d761fe0462ba0f671a237d0bb35e3579b8ba0e8/src/libstd/panicking.rs#L301), backing (as we will see) panics from `core::panic!` and built-in panics (from arithmetic overflow or out-of-bounds array/slice indexing).
This obtains as input a [`PanicInfo` ](https://doc.rust-lang.org/core/panic/struct.PanicInfo.html), and it has to turn that into arguments for `rust_panic_with_hook`.
In particular, a panic hook that looks at the `message` field of the `PanicData` it is passed will *not* be able to see the message in a `std::panic!("do panic")`, but it *will* see the message in a `std::panic!("panic with data: {}", data)` as the latter passes through `begin_panic_fmt` instead.
That seems quite surprising. (But also note that `PanicData::message()` is not stable yet.)
+* [`update_count_then_panic`](https://github.com/rust-lang/rust/blob/7d761fe0462ba0f671a237d0bb35e3579b8ba0e8/src/libstd/panicking.rs#L488) is the odd one out: this entry point backs [`resume_unwind`](https://doc.rust-lang.org/nightly/std/panic/fn.resume_unwind.html), and it actually does *not* call the panic hook.
+ Instead, it dispatches to the panic runtime immediately.
+ Like, `begin_panic`, it lets the caller pick an arbitrary payload.
+ Unlike `begin_panic`, the caller is responsible for boxing and unsizing the payload; `update_count_then_panic` just forwards that pretty much verbatim to the panic runtime.
+
## Panic Handler
All of the `std::panic!` machinery is really useful, but it relies on heap allocations through `Box` which is not always available.