· via Hacker News – Front Page (native)
Microsoft-backed Call Graph Analyzer maps panic paths in Rust via monomorphized MIR
Tweede golf, working with Microsoft under the Open Device Partnership, released the Call Graph Analyzer, which extracts a call graph from Rust's monomorphized MIR to flag functions in a compiled binary that can panic.

Microsoft and Tweede golf ship a panic finder for Rust
Rust consultancy Tweede golf has developed and released the Call Graph Analyzer (CGA), a tool built in collaboration with Microsoft under the Open Device Partnership. According to the company's blog post, which reached the front page of Hacker News, the tool addresses a question the team fields regularly from Rust developers: how to get panics out of their code.
CGA works by extracting the call graph from monomorphized MIR, the intermediate representation the Rust compiler produces after generics have been resolved into concrete types. Because that graph reflects what will actually end up in the compiled binary, it can be walked to determine which functions are capable of panicking. Running cargo cga check surfaces those paths as compiler-style errors: the post shows a diagnostic flagging a call to strict_sub on u64 as capable of panicking, pinpointed to an exact file, line and column in the source.
Why eliminate panics at all
As the post explains, a Rust panic is the language's mechanism for error conditions that are not expected to be recoverable, either a bug inside a function or a caller violating its entry conditions, such as operands that overflow strict arithmetic operations. Developers who want different behaviour can return Result or Option types via checked arithmetic, let operations wrap silently and document it, or, less usefully, never return at all.
The authors are candid that fully eliminating panics is both difficult and largely misguided: code is rarely free of assumptions, and converting every failure into a returned error merely shifts the burden up the call stack until something aborts at the root anyway. Their recommendation is to make panic paths explicit, reason about them deliberately, and run regression analysis so newly introduced panic paths trigger a notification.
That said, the post identifies cases where removal is justified. On embedded devices, panic formatting code and its associated strings bloat binaries, and options like defmt::panic or -Cpanic=immediate-abort trade size for debuggability. In code paths that must never fail, such as an internet-facing service where a crash amounts to a self-inflicted denial of service, or a device's firmware-update and bootloader path, an unrecoverable panic is unacceptable. Panics are also problematic inside panic-handling machinery itself, since unwinding through a Drop implementation can abort the program, and a panic inside a custom #[panic_handler] is simply not allowed. For everything else, the authors suggest top-level recovery mechanisms: watchdog timers and recovery images on embedded devices, catch_unwind on hosts, with caveats.
How it stacks up against existing tools
The post surveys earlier approaches: rustig and findpanics, which mine DWARF debug information from ELF artifacts; two projects named cargo-callgraph, one built on the compiler's HIR and one on rust-analyzer; charon, a MIR exporter; and the linker-based no-panic and dont_panic crates.
Each has blind spots, according to Tweede golf. Linker tricks only detect panics if the final binary contains none at all, and they cannot work on libraries. DWARF analysis loses information when panic machinery is inlined or disappears during linking. HIR analysis sees only the current crate, missing dependencies, the standard library, and compiler-inserted checks such as bounds assertions that materialize late in code generation depending on compiler flags.
MIR is the sweet spot, the authors argue, because it can see all dependency code, including the standard library, before optimization removes anything. That is why CGA builds on it. The cost is false positives: the analysis runs before LLVM prunes unreachable code, so the tool may flag panic paths that a full compile would eliminate. The authors frame the new approach as simultaneously better and worse than what came before, depending on the use case.
Why it matters
Panics are Rust's implicit failure channel, and most teams discover them only when they fire in testing or production. By statically modeling the whole compiled program, dependencies and standard library included, CGA gives embedded developers, bootloader authors and service maintainers a way to audit failure paths before shipping. Its known limitation, conservative over-reporting, means results still need human review, but that friction arguably serves the stated goal: not zero panics, which the authors call unrealistic, but panic paths that are visible, understood and tracked over time. For teams writing firmware under the Open Device Partnership and for any Rust developer who wants a binary's failure behaviour on the record, CGA is a meaningful addition to the existing toolbox.
- #rust
- #static-analysis
- #developer-tools
- #embedded
- #open-source