# Panicking in Rust
<!-- toc -->
## Step 1: Invocation of the `panic!` macro.
There are actually two panic macros - one defined in `core`, and one defined in `std`.
This is due to the fact that code in `core` can panic. `core` is built before `std`,
but we want panics to use the same machinery at runtime, whether they originate in `core`
or `std`.
### core definition of panic!
The `core` `panic!` macro eventually makes the following call (in `library/core/src/panicking.rs`):
```rust
// NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
extern "Rust" {
#[lang = "panic_impl"]
fn panic_impl(pi: &PanicInfo<'_>) -> !;
}
let pi = PanicInfo::internal_constructor(Some(&fmt), location);
unsafe { panic_impl(&pi) }
```
Actually resolving this goes through several layers of indirection:
1. In `compiler/rustc_middle/src/middle/weak_lang_items.rs`, `panic_impl` is
declared as 'weak lang item', with the symbol `rust_begin_unwind`. This is
used in `rustc_hir_analysis/src/collect.rs` to set the actual symbol name to
`rust_begin_unwind`.
Note that `panic_impl` is declared in an `extern "Rust"` block,
which means that core will attempt to call a foreign symbol called `rust_begin_unwind`
(to be resolved at link time)
2. In `library/std/src/panicking.rs`, we have this definition:
```rust
/// Entry point of panic from the core crate.
#[cfg(not(test))]
#[panic_handler]
#[unwind(allowed)]
pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
...
}
```
The special `panic_handler` attribute is resolved via `compiler/rustc_middle/src/middle/lang_items`.
The `extract` function converts the `panic_handler` attribute to a `panic_impl` lang item.
Now, we have a matching `panic_handler` lang item in the `std`. This function goes
through the same process as the `extern { fn panic_impl }` definition in `core`, ending
up with a symbol name of `rust_begin_unwind`. At link time, the symbol reference in `core`
will be resolved to the definition of `std` (the function called `begin_panic_handler` in the
Rust source).
Thus, control flow will pass from core to std at runtime. This allows panics from `core`
to go through the same infrastructure that other panics use (panic hooks, unwinding, etc)
### std implementation of panic!
This is where the actual panic-related logic begins. In `library/std/src/panicking.rs`,
control passes to `rust_panic_with_hook`. This method is responsible
for invoking the global panic hook, and checking for double panics. Finally,