Что происходит при панике в Rust: от макроса до раскрутки стека

Когда я впервые увидел backtrace паники в Rust, я решил, что это просто аналог исключения. Вызвал panic!, стек раскрутился, деструкторы вызвались, поток умер. Примерно как throw в C++ или raise в Python. Потом я попытался передать панику через FFI-границу, и программа молча упала без backtrace. Потом обнаружил, что catch_unwind перестаёт работать, если в Cargo.toml поменять panic = "unwind" на panic = "abort". Потом выяснил, что двойная паника (когда деструктор паникует во время раскрутки) убивает процесс безусловно, и это не баг, а так задумано.
Оказалось, что за простым panic!("oops") стоит сложная система из сменных runtime-ов, платформозависимой раскрутки стека и кучи граничных случаев...


















