Hack to allow .unwrap() to get file_name / line_number?

I have a macro, my_todo!(), which behaes just like todo!() with one difference:

In my_todo!(), it grabs the current file_name / line_number, and logs it via HTTP request before dying.

Now, I understand that Option/Result.unwrap() is a function -- and functions unlike macros, don't have access to file_name/line_number.

I also understand that I can create macro my_unwrap!() ... but that breaks, the flow, i.e. f.unwrap().something().unwrap().otherthing.unwrap() reads much better than

my_unwrap!( my_unwrap!( my_unwrap!(f).something()).otherthing )

So I am wondering if there is a way to have something that behaves like 'unwrap', is still "in the flow" of the expression, but on failure, allows me to log filename / line_number.


Postfix macros do not exist yet.

The closest things I can think of are using unwrap_or_else:


Or putting a procedural macro on the entire block or function that inserts your macro. Not sure how feasible this is though.

    f.something().unwrap() // <- gets replaced
1 Like

Option::unwrap and Result::unwrap do have access to the caller's filename and line number, thanks to the #[track_caller] attribute. That's why, starting in Rust 1.42, they print the filename and line number of the caller on failure. For more details, see RFC 2091.

Some of the implementation details for this are still unstable, but if you need more customized behavior in stable Rust you can implement something similar using the backtrace crate, as illustrated by the trace_caller proc macro.


They could be faked within a larger macro context. e.g. I faked expression attribute macros this way in closure_attr — Rust library // Lib.rs

1 Like

Note that the Location mechanism does not work by reading the stack, but by implicitly passing an &Location argument. Therefore, making use of backtrace capturing instead would change the performance characteristics and the data reported in edge cases.

1 Like