-
-
Notifications
You must be signed in to change notification settings - Fork 75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add an impl Format for PanicInfo #856
Conversation
3b7823f
to
6c13865
Compare
The deprecation notice says:
Do you have some example output of a panic handler using this formatter, where it did in fact return something useful? Going forward, I wonder how we design a handler that works on both <= 1.80 and >= 1.81 |
I also asked this on the wg-embedded Zulip channel. |
I tried to mirror the From what I can see, the deprecation note was added in the nightly channel when |
A |
@m-ou-se is there a recommendation for how people should render a |
The only stable way today is to Display the PanicInfo itself. That will print the standard The only thing we're adding in the future is adding a .message() to get the |
To me the root reason for making this change is to remove a dependency on @m-ou-se any ideas how one could make it possible to implement efficient |
Yes, that's exactly why I was working on adding core::panic::PanicInfo::message(). ^^ That method will be stable in 1.81, most likely. |
Haha, well that makes sense! Great! I suppose one has to just patiently wait then... I guess the reason why I didn't make the connection immediately is that Regarding this PR, I guess I should remove the downcast code, but should I also add a nightly feature flag that prints |
I'm confused, you want to be able to format the panic message without pulling in the code required to format that panic message? That fmt::Arguments only pulls in whatever is used by the panic message. If that panic message is just a static string literal, it will not pull in any padding/formatting code etc. But yes, if that panic message contains a formatted number or something (e.g. |
Yes, because this is defmt, a deferred formatting mechanism where strings are interned into debug sections and replaced with small integers in the code. What then goes over the logging transport is the numeric ID of the interned string, and a simple byte-serialisation of any fundamental types used as arguments. Where the argument is not a fundamental type, we implement the Thus the whole point of this crate is to bypass the expensive I guess if the panic message is |
Yeah, that's my point. Display'ing PanicMessage is fine then. fmt::Arguments for a static string doesn't pull in any formatting code. For the |
Hey, great pointers on the nuances between how static msgs are handled vs when they need integer interpolation. To throw another idea on the stack: could Or would that not be worth it, since we wouldn't get a monomorphized version of whatever struct impls EDIT: I'll start on a separate PR to try to intercept EDIT 2: This probably won't work since all the formatting is entirely encapsulated, ie the only way to format |
@m-ou-se do you have any leads for how one would best offload the number formatting from What we'd want to avoid is to have the number formatting code on the actual device; instead As mentioned above, I see that We have the I'd imagine wanting to be able to write a function at some point that does something like: fn defmt_write_args(f: defmt::Formatter, args: core::fmt::Arguments) {
for part in args.parts() {
match part {
Part::LitStr(s) => defmt::write!("{=str}", s),
Part::Placeholder(p) => {
if let Some(v) = p.value().downcast_ref::<u8>() {
// TODO: if we imagine that `p` has some type similar to `core::fmt::rt::Placeholder`, then
// params like p.position, p.align, p.precision, p.width could also be sent along to the host here
// to be used to influence formatting.
defmt::write!("{=u8}", v);
} else if let Some(v) = p.value().downcast_ref::<u16>() {
defmt::write!("{=u16}", v);
}
//...
}
}
}
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
Can you please also add some examples to the snapshot tests? The file is firmware/qemu/src/bin/log.rs
and you can update the output with cargo xtask test-snapshot --overwrite
.
defmt/src/impls/core_/panic.rs
Outdated
#[allow(deprecated)] // Deprecated on nightly | ||
if let Some(msg) = self.payload().downcast_ref::<&'static str>() { | ||
crate::write!(f, "\n{=str}", msg); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we write something else in case the payload is not a static string? Something like <panic info>
maybe?
@Urhengulas thanks for the PR review! As per the above conversation I consider this PR to not be ready to merge since we are waiting to learn more from I'm happy to make the changes that you requested once we have some clarity on the above points. |
Ah okay, I understood that the current version is not ideal but better than nothing. And then once I will convert it to a draft PR. Please un-draft as soon as it is ready for merging again. |
3b0165d
to
75099f9
Compare
@Urhengulas ah sure, we can do it that way, to add For now I completely removed the I didn't find a way to update the snapshot tests because it isn't possible to construct a As I think this is as good as things can get right now without waiting for the |
@dflemstr said:
One (slightly involved) way I see, is to add a new snapshot test binary (probablu To add a new snapshot test, just create the binary, add it to the Line 30 in 5d467c2
panic_internals ) to Lines 79 to 83 in 5d467c2
And then you can run it and create the output with |
@Urhengulas thanks for the pointers! I had gone down the route of trying to enable the compiler-internal feature flag, but even when I tried to disable all the safeguards: #![allow(internal_features)]
#![feature(allow_internal_unstable, panic_internals)]
#[allow_internal_unstable(panic_internals)]
fn test_panic_info() {
//...
} ...it still wouldn't compile. However it was helpful that you explained how to add a separate snapshot test, which made it possible for now to have a separate test binary to let the test panic exactly once and succeed on panic. |
For the record, I don't know why the semver check is failing, and I think it is unrelated to this PR. |
This impl is useful for panic handlers that use
defmt
to report panics, for example,panic_probe
with thedefmt
feature.The default
core::fmt
implementation forPanicInfo
pulls in number formatting, padding support,dyn Debug/Display
dependencies, etc. which can cause a lot of unnecessary code to be pulled in just to formatPanicInfo
.