dtolnay/no-panic
{ "createdAt": "2018-08-03T20:17:43Z", "defaultBranch": "master", "description": "Attribute macro to require that the compiler prove a function can't ever panic", "fullName": "dtolnay/no-panic", "homepage": "", "language": "Rust", "name": "no-panic", "pushedAt": "2025-11-20T18:06:39Z", "stargazersCount": 1164, "topics": [], "updatedAt": "2025-11-23T21:47:16Z", "url": "https://github.com/dtolnay/no-panic"}#[no_panic]
Section titled “#[no_panic]”A Rust attribute macro to require that the compiler prove a function can’t ever panic.
[dependencies]no-panic = "0.1"use no_panic::no_panic;
#[no_panic]fn demo(s: &str) -> &str { &s[1..]}
fn main() { println!("{}", demo("input string"));}If the function does panic (or the compiler fails to prove that the function cannot panic), the program fails to compile with a linker error that identifies the function name. Let’s trigger that by passing a string that cannot be sliced at the first byte:
fn main() { println!("{}", demo("\u{1f980}input string"));} Compiling no-panic-demo v0.0.1error: linking with `cc` failed: exit code: 1 | = note: /no-panic-demo/target/release/deps/no_panic_demo-7170785b672ae322.no_panic_demo1-cba7f4b666ccdbcbbf02b7348e5df1b2.rs.rcgu.o: In function `_$LT$no_panic_demo..demo..__NoPanic$u20$as$u20$core..ops..drop..Drop$GT$::drop::h72f8f423002b8d9f': no_panic_demo1-cba7f4b666ccdbcbbf02b7348e5df1b2.rs:(.text._ZN72_$LT$no_panic_demo..demo..__NoPanic$u20$as$u20$core..ops..drop..Drop$GT$4drop17h72f8f423002b8d9fE+0x2): undefined reference to `
ERROR[no-panic] !: detected panic in function `demo` ' collect2: error: ld returned 1 exit statusThe error is not stellar but notice the ERROR[no-panic] part at the end that provides the name of the offending function.
Caveats
Section titled “Caveats”-
Functions that require some amount of optimization to prove that they do not panic may no longer compile in debug mode after being marked
#[no_panic]. -
Panic detection happens at link time across the entire dependency graph, so any Cargo commands that do not invoke a linker will not trigger panic detection. This includes
cargo buildof library crates andcargo checkof binary and library crates. -
The attribute is useless in code built with
panic = "abort". Code must be built withpanic = "unwind"(the default) in order for any panics to be detected. After confirming absence of panics, you can of course still ship your software as apanic = "abort"build. -
Const functions are not supported. The attribute will fail to compile if placed on a
const fn.
If you find that code requires optimization to pass #[no_panic], either make
no-panic an optional dependency that you only enable in release builds, or add a
section like the following to your Cargo.toml or .cargo/config.toml to enable
very basic optimization in debug builds.
[profile.dev]opt-level = 1If the code that you need to prove isn’t panicking makes function calls to non-generic non-inline functions from a different crate, you may need thin LTO enabled for the linker to deduce those do not panic.
[profile.release]lto = "thin"If thin LTO isn’t cutting it, the next thing to try would be fat LTO with a single codegen unit:
[profile.release]lto = "fat"codegen-units = 1If you want no_panic to just assume that some function you call doesn’t panic,
and get Undefined Behavior if it does at runtime, see [dtolnay/no-panic#16]; try
wrapping that call in an unsafe extern "C" wrapper.
[dtolnay/no-panic#16] !: https://github.com/dtolnay/no-panic/issues/16
Acknowledgments
Section titled “Acknowledgments”The linker error technique is based on [Kixunil]‘s crate [dont_panic]. Check
out that crate for other convenient ways to require absence of panics.
[Kixunil] !: https://github.com/Kixunil
[dont_panic] !: https://github.com/Kixunil/dont_panic
License
Section titled “License”Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.