-
-
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
unwrap alternative? #161
Comments
Here's a copypaste-ready implementation, in case someone finds it useful... macro_rules! depanic {
($( $i:expr ),*) => {
{
defmt::error!($( $i ),*);
panic!();
}
}
}
pub trait Dewrap<T> {
/// dewrap = defmt unwrap
fn dewrap(self) -> T;
/// dexpect = defmt expect
fn dexpect<M: defmt::Format>(self, msg: M) -> T;
}
impl<T> Dewrap<T> for Option<T> {
fn dewrap(self) -> T {
match self {
Some(t) => t,
None => depanic!("unwrap failed: enum is none"),
}
}
fn dexpect<M: defmt::Format>(self, msg: M) -> T {
match self {
Some(t) => t,
None => depanic!("unexpected None: {:?}", msg),
}
}
}
impl<T, E: defmt::Format> Dewrap<T> for Result<T, E> {
fn dewrap(self) -> T {
match self {
Ok(t) => t,
Err(e) => depanic!("unwrap failed: {:?}", e),
}
}
fn dexpect<M: defmt::Format>(self, msg: M) -> T {
match self {
Ok(t) => t,
Err(e) => depanic!("unexpected error: {:?}: {:?}", msg, e),
}
}
} |
I started working with this, it works, but it is a bit cumbersome to have both It would be really nicer to be able to do |
No, there is no way to override |
Would it be possible to provide |
I think not without specialization, if we want it to work with both |
@Dirbaio now that |
I've seen the work on panic/assert, very nice! The problem with that implementation of I've experimented with
One upside is that would allow us to print the failed expression, like asserts: "Unwrap of foo.bar() failed". AFAICT there's no way to make "postfix/method" syntax macros like So I'm not sure what to do :( |
@Dirbaio will |
I looked at it, the problem is it gives us the caller information at runtime, whereas we want it at compile time to put it in the defmt log metadata. Yes, it's possible to use the info at runtime like If this overhead is acceptable to you, you can already achieve this today with |
DWARF has facilities for macro-expanded code, maybe we "just" need to fix this on the host side by making use of that? |
Ah, that would only help with the less nice Don't we get a backtrace when the panic happens though? That should contain the frame that called |
in my experience the unwind is not reliable enough with optimizations (and building without is not viable: slow and doesn't fit in flash). It does work for getting a rough location, but many times I've had to stick a few log calls before unwraps to figure things out. IMO it's good to have guaranteed-accurate location info in unwraps, for UX and for consistency with logs/panic/assert. I think the best solution is adding Maybe we can do a single macro for both instead: I'll work on this if we're OK with the design. |
I would be interested in hearing more about where / when this happens. It may an upstream issue in
I was aware of this but thought it was not much of an issue because the real location is printed in the backtrace, but if that's not the case then perhaps we should consider using something else.
(you may be referring to the DWARF stuff used in the backtrace (addr2line); that one maps a PC (Program Counter) address to a location, or to a list of inlined function frames. Not applicable here because it would require dewrap obtaining the PC of the caller frame somehow)
we'll get back to you |
with #273 merged, can we close this? |
yup, this is now done 🎉 |
uwnrap()
on a Result is quite convenient, but it's not usable with defmt since it requires the error type to be fmt::Debug, which is not useful to print it with defmt.A solution could be add a trait
defmt::Unwrap
(or maybeDewrap
?) and implement it for Result, which does the same asunwrap()
but printing the result with defmt.The text was updated successfully, but these errors were encountered: