I'm working on a procedural macro, and I found that compiler does not give information about proc-macro crates when the procedural macro panics. I tried to override panic!
to print a location:
macro_rules! std_panic {
($($args:tt)+) => {{
panic!($($args)*);
}};
}
/// panic! with location reporting.
macro_rules! panic {
($($args:tt)+) => {{
std_panic!("{}\n --> {}:{}:{}", format_args!($($args)*), file!(), line!(), column!());
}};
}
But the compiler fails with
error: recursion limit reached while expanding the macro `std_panic`
--> src/lib.rs:30:9
|
30 | std_panic!("{}\n --> {}:{}:{}", format_args!($($args)*), file!(), line!(), column!());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
54 | _ => unimplemented!("handling tuple struct"),
in this macro invocation
|
= help: consider adding a `#![recursion_limit="131072"]` attribute to your crate
I set the limit to 65536
to prove that this is related to recursive expansion.
According to the macros chapter of The Rust Programming Language, first edition, my own panic!
is not visible to std_panic!
, so it should use panic!
from the standard library.
I also tried
#![feature(no_std)]
#![no_std]
#[macro_use(panic)]
extern crate std;
but it doesn't work.
Yes, you can override a macro from the standard library:
macro_rules! panic {
($($arg:tt),*) => {};
}
fn main() {
panic!("Exit");
println!("Or not...");
}
No, you cannot then call the macro you just shadowed.
Macros are expanded at the site of use. In your example, when you try to use panic!
, it expands to std_panic!
which in turn expands to panic!
. At that point, your own panic!
is the one in scope.
This simpler example shows that a macro calls whatever do_foo
happens to be in scope where the macro is expanded. Note that there isn't even a do_foo
defined where the macro is:
macro_rules! foo {
() => {
do_foo()
};
}
fn main() {
{
fn do_foo() {
println!("1")
}
foo!();
}
{
fn do_foo() {
println!("2")
}
foo!();
}
}
Instead, you will need to refer to the original macro via its complete path (available since Rust 1.30):
macro_rules! panic {
($($args:tt)+) => {{
std::panic!("{}\n --> {}:{}:{}", format_args!($($args)*), file!(), line!(), column!());
}};
}
See also:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With