Panic_handler free #![no_std] targets

We currently requiere every #![no_std] bin/staticlib/cdylib crate to designate a #[panic_handler] function and to set panic=abort or implement a lang_item. Wouldn't it make sense to lower this requirements to allow tragets not to specify #[panic_handler] if the entire code is free of any panic invocations. A common use case could be code, where panicing would be fatal e.g. writing an OS kernel or an Rust version of the Unix init program.

Not implementing a #[panic_handler] vs. implementing a dummy handler has the advantage of ensuring that the "this code does never panic" assumption is correct and avoids defining extra symboles in you code.

This is similar to how one only needs to specify a global allocator if one uses allocation.

You need to specify a global allocator if liballoc is included, even if it isn't used at all. Following this logic as libcore has panicking methods, that means that any crate using libcore (that is everyone that doesn't use an unstable feature to disable libcore) would need a panic handler. Instead it would have to consider which functions are actually codegened. The exact set of functions that is codegened inside an rlib is unstable. (the compiler is free to delay codegen until the crate that actually uses the function or to eagerly codegen generic functions) At the moment a lot of panicking functions are codegened for libcore like core::panicking::panic, which means that a panic handler would be necessary even when taking into account which functions are codegened. Due to the way rust-for-linux compiles rust code, it is also not possible to delay codegen until the final bin/cdylib/staticlib library as rust-for-linux never compiles a bin/cdylib/staticlib, but instead manually links the --emit obj object files for rlibs. It is also not like we can pretend that the panic handler is not necessary. Without --gc-sections (which is disabled by default for rust-for-linux I believe) you will get a linker error.


I think panics are pretty much equivalent to oopses in Linux. They are normally supposed to bring down a thread, but not necessarily the whole process. Rust-for-linux currently implements panics as kernel panics, which matches the default for -Cpanic=abort, but I think it would be safe to implement it as an oops even with -Cpanic=abort.

1 Like

Thanks for you reply.

I see. It certainly doesn't make sense to make this crate dependend, if one looses core. In that case Rust would have to track whether a function can panic (doesn't the compiler allready do that?) and check if such a function is used in any extern "C" function. To satisfy the panic_handler refrences in dead code functions, one would probably have to generate some sort of dummy target then.

I don't how things are handled in Rust-for-Linux. I had of course Linus' comment on panics in my head, but I was more thinking more general there.

Probably the idea is not feasable or practical limitations make it not really useful in most settings, but this was just something I had on my mind.

Yup, I think currently rustc uses panicking core and generates panicking code for things like [], and only later they're purged via the LLVM optimizer, or maybe even the linker. So when processing source code rustc doesn't really know if panics are relevant.

But maybe there could be panic=abort-i-really-mean-it that generates literally abort() or illegal instruction for every panic instead of a call to a panic handler.

This is panic_immediate_abort (Allow asserts and panics to abort process quietly. · Issue #54981 · rust-lang/rust · GitHub).


I've seen some people use a panic handler which links to an external function that doesn't exist. That way, you can "detect" if the code can panic or not by getting a link error if there is any code path which can lead to the panic handler being called.

Crude, and perhaps overly conservative (if the optimizer misses something and leaves in a panic path which doesn't occur in practice), but it does work without any special new compiler options or anything else like that.

1 Like

Here's a crate that does exactly that:

1 Like