What the title says.
panic_fmt
is a language item, a compiler detail, that has been with us since ever. Until recently, this language item was the only way to define what panic!
does in no_std
applications / crates. As of the latest nightly this language item has been removed in favor of the #[panic_implementation]
attribute which offers a type checked way of declaring the behavior of panic!
. #[panic_implementation]
is also what we plan to stabilize in the near future.
Rationale
The panic_fmt
function with its "unrolled" arguments was prone to silent breakage. At some point the signature of panic_fmt
changed from fn(Arguments, file: &'static str, line: u32)
to fn(Arguments, file: &'static str, line: u32, col: u32)
; this small change didn't cause a compiler error in crates that defined this language item but significantly increased the binary size of all downstream users of those crates.
#[panic_implementation]
changes the signature of the panic handler to fn(&PanicInfo)
. PanicInfo
is a struct
that contains information about the panic!
invocation, like the location of the panic (file, line, column). This struct
has private fields and can be extended without causing (silent) breakage.
Finally, language items are, in general, compiler implementation details and there's no plan to stabilize #[lang = "*"]
. By turning the panic_fmt
language into its own attribute we can stabilize it independently from the other language items.
Dealing with the breakage
This change is a breaking change and some action may be required from maintainers of no_std
crates.
panic_fmt
author
If you are the author of a crate that provides the panic_fmt
language item you'll have to update your crate to use #[panic_implementation]
. Basically, you will have to go from:
#![feature(lang_items)]
use core::intrinsics;
#[lang = "panic_fmt"]
unsafe extern "C" fn panic_fmt(
_args: core::fmt::Arguments,
_file: &'static str,
_line: u32,
_col: u32,
) -> ! {
intrinsics::abort()
}
to:
#![feature(panic_implementation)]
use core::intrinsics;
use core::panic::PanicInfo;
#[panic_implementation]
fn panic(_info: &PanicInfo) -> ! {
unsafe { intrinsics::abort() }
}
Check the API documentation of PanicInfo
to learn how to access the panic location and the arguments passed to panic!
. Also, it may not be obvious from the API docs but formatting PanicInfo
using Display
will produce the familiar string: "panicked at '$reason', file.rs:4:2"
.
panic_fmt
user
When you compile your binary crate you'll encounter the following error:
error[E0522]: definition of an unknown language item: `panic_fmt`
Here's how to fix it.
In the Cortex-M ecosystem, we isolated definitions of the panic_fmt
language item into their own crates. If you were using any of those panic-impl
crates all you have to do is bump the minor version of the dependency.
If you were depending on some other crate that provided the panic_fmt
language item let the author know about the breakage; or if you feel up to the task send them a pull request!
If you encounter any issue with #[panic_implementation]
please report it in the tracking issue.
This change is part of the effort towards making embedded development possible on the stable channel. (Woot! We are almost done)