No-Panic Rust: A Nice Technique for Systems Programming

Site stability issues

  • Many readers report the article page hard-crashing or freezing mobile browsers (Safari iOS, Chrome/Brave/Pixel/Android, DDG) and even some desktop setups.
  • Other posts on the same blog work fine; commenters suspect the large number of embedded Godbolt iframes.
  • An archived Web Archive link is provided as a workaround.

Desire for compiler-level no-panic guarantees

  • Multiple commenters are surprised Rust lacks a built-in -nopanic / no_panic crate attribute to make any reachable panic a compile error.
  • Concern: relying on the optimizer to DCE panic paths feels fragile and non-obvious, especially given changing optimizations between releases.

Existing mechanisms and their limits

  • panic = "abort" removes unwinding and a chunk of runtime but does not guarantee absence of panics; it just changes behavior.
  • Crates like no-panic, no-panics-whatsoever, and panic-analyzer try to enforce or detect panics, but:
    • Some use link-time tricks and are not 100% reliable.
    • They are per-function or heuristic and don’t scale cleanly to whole dependency graphs.
  • Clippy can lint for common panicking patterns, but this is not a proof.
  • catch_unwind allows recovery but retains panic runtime and is not guaranteed to catch all panics; code is not generally “exception-safe” under unwinding.

Panics vs errors: semantics and design

  • One camp: panics should be effectively unrecoverable, reserved for logic bugs / invalid state; normal failure should use Result/Option.
  • Another camp: Rust explicitly designs panics to be recoverable at coarse-grained boundaries (thread, request handler) and this is important for servers.
  • Debate over panic = abort:
    • Pro: avoids inconsistent in-memory state; simpler mental model in safety-sensitive systems.
    • Con: turns any bug into process-wide DoS; unwinding + poisoning can be acceptable for most web-style workloads.

Standard library, allocation, and no-panic std

  • Many std APIs panic (indexing, allocation, some I/O); a crate-wide no_panic would currently only work no_std or with heavy restrictions.
  • There is incremental work in std on non-panicking or fallible variants (get, push_within_capacity, etc.), but lots remains.
  • Some argue OOM panics are acceptable in most environments; others want clearer separation of allocation failures vs other panics, especially for embedded/safety-critical code.
  • Idea raised of a “nopanic-std” or specialized stdlib build, and of compiling std with custom panic handlers (panic_abort, panic_immediate_abort) to cut bloat.

Using optimization to eliminate panics

  • The article’s technique—using assert_unchecked and invariants so the optimizer can delete panic paths—is seen as clever but dangerous.
  • Some point out that such wrapper functions should be unsafe and named like assume_invariant_holds, since they assert rather than check.
  • Discussion notes:
    • If the optimizer can prove an assert is impossible, it removes the panic; this can be treated as a kind of proof.
    • But guarantees are limited: complex code, recursion, and undecidability (Rice’s theorem) mean many invariants can’t be proven.
    • Depending on optimizer behavior is brittle across compiler versions and optimization levels.

Debugging, tooling, and transitive panics

  • Several people report real-world crashes from overuse of panic! in library code where Result would have allowed graceful recovery.
  • Simple grepping for panic! is insufficient due to panicking methods (unwrap, indexing, some std APIs) and deep transitive dependencies.
  • Tools like panic-analyzer and no-panic help, but don’t give an easy, global “this crate never panics” guarantee.
  • Some wish for a sanitizer that dynamically verifies “no panic” along a call graph, analogous to race or blocking detectors.

Broader design and alternatives

  • Some suggest other languages/tools (e.g., Zig, formal-verification-oriented Rust variants, Verus, TLA+, Coq, Idris/Agda) for stronger guarantees.
  • Side discussion on mmap-based data structures (Cap’n Proto-style) and whether Rust’s standard collections could ever be made mmap-backed in a first-class way.