Bug: 175299806

Clone this repo:
  1. e7e811d Upgrade no-panic to 0.1.17 by Jeff Vander Stoep · 3 days ago master
  2. 73a6af6 Upgrade no-panic to 0.1.16 by Jeff Vander Stoep · 8 weeks ago main-16k-with-phones
  3. 74b42a9 Merge "Refresh Android.bp, cargo2android.json, TEST_MAPPING." am: 0b0cd5de9e am: ec034b50da am: 51c06f7f8f am: f228529625 by Joel Galenson · 1 year, 2 months ago android13-dev android13-frc-adbd-release android13-frc-art-release android13-frc-cellbroadcast-release android13-frc-conscrypt-release android13-mainline-adservices-release android13-mainline-appsearch-release android13-mainline-go-adbd-release android13-mainline-go-adservices-release android13-mainline-go-appsearch-release android13-mainline-go-media-swcodec-release android13-mainline-go-mediaprovider-release android13-mainline-go-networking-release android13-mainline-go-neuralnetworks-release android13-mainline-go-odp-release android13-mainline-go-os-statsd-release android13-mainline-go-permission-release android13-mainline-go-resolv-release android13-mainline-go-scheduling-release android13-mainline-go-sdkext-release android13-mainline-go-tethering-release android13-mainline-go-tzdata4-release android13-mainline-go-uwb-release android13-mainline-go-wifi-release android13-mainline-tzdata4-release android13-mainline-uwb-release android13-qpr1-release android13-qpr1-s1-release android13-qpr1-s2-release android13-qpr1-s3-release android13-qpr1-s4-release android13-qpr1-s5-release main-16k aml_ads_331131000 aml_ase_331011020 aml_ase_331112000 aml_go_adb_330913000 aml_go_ads_330913000 aml_go_ase_330913000 aml_go_mpr_330912000 aml_go_net_330913000 aml_go_neu_330912000 aml_go_odp_330912000 aml_go_per_330912000 aml_go_res_330912000 aml_go_sch_330911000 aml_go_sdk_330810000 aml_go_sta_330911000 aml_go_swc_330913000 aml_go_tet_330914010 aml_go_tz4_330912000 aml_go_uwb_330912000 aml_go_wif_330911000 aml_tz4_331012000 aml_tz4_331012040 aml_tz4_331012050 aml_tz4_331314010 aml_uwb_330810010 aml_uwb_331015040 aml_uwb_331115000 aml_uwb_331310030 android-13.0.0_r16 android-13.0.0_r17 android-13.0.0_r18 android-13.0.0_r19 android-13.0.0_r20 android-13.0.0_r21 android-13.0.0_r22 android-13.0.0_r23 android-13.0.0_r24 t_frc_adb_330444000 t_frc_art_330443060 t_frc_ase_330444010 t_frc_cbr_330443000 t_frc_con_330443020 t_frc_odp_330442000
  4. f228529 Merge "Refresh Android.bp, cargo2android.json, TEST_MAPPING." am: 0b0cd5de9e am: ec034b50da am: 51c06f7f8f by Joel Galenson · 1 year, 2 months ago
  5. 51c06f7 Merge "Refresh Android.bp, cargo2android.json, TEST_MAPPING." am: 0b0cd5de9e am: ec034b50da by Joel Galenson · 1 year, 2 months ago

#[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.1
error: linking with `cc` failed: exit code: 1
  |
  = note: /no-panic-demo/target/release/deps/no_panic_demo-7170785b672ae322.no_p
anic_demo1-cba7f4b666ccdbcbbf02b7348e5df1b2.rs.rcgu.o: In function `_$LT$no_pani
c_demo..demo..__NoPanic$u20$as$u20$core..ops..drop..Drop$GT$::drop::h72f8f423002
b8d9f':
          no_panic_demo1-cba7f4b666ccdbcbbf02b7348e5df1b2.rs:(.text._ZN72_$LT$no
_panic_demo..demo..__NoPanic$u20$as$u20$core..ops..drop..Drop$GT$4drop17h72f8f42
3002b8d9fE+0x2): undefined reference to `

          ERROR[no-panic]: detected panic in function `demo`
          '
          collect2: error: ld returned 1 exit status

The error is not stellar but notice the ERROR[no-panic] part at the end that provides the name of the offending function.

Compiler support: requires rustc 1.31+

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 build of library crates and cargo check of binary and library crates.

  • The attribute is useless in code built with panic = "abort".

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 Cargo.toml to enable very basic optimization in debug builds.

[profile.dev]
opt-level = 1

If 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 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.

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.

License