gpt4 book ai didi

macros - 我可以用我自己的自定义宏覆盖标准库中的宏吗?

转载 作者:行者123 更新时间:2023-11-29 07:54:21 25 4
gpt4 key购买 nike

我正在处理一个过程宏,我发现编译器在过程宏崩溃时不提供有关 proc-macro crates 的信息。我试图覆盖 panic! 来打印一个位置:

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!());
}};
}

但是编译器失败了

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

我将限制设置为65536,以证明这与递归扩展有关。

根据 the macros chapter of The Rust Programming Language, first edition ,我自己的 panic!std_panic! 是不可见的,所以它应该使用标准库中的 panic!

我也试过

#![feature(no_std)]
#![no_std]
#[macro_use(panic)]
extern crate std;

但它不起作用。

最佳答案

,您可以覆盖标准库中的宏:

macro_rules! panic {
($($arg:tt),*) => {};
}

fn main() {
panic!("Exit");
println!("Or not...");
}

,您不能调用您刚刚隐藏的宏。

宏在使用的地方展开。在您的示例中,当您尝试使用 panic! 时,它会扩展为 std_panic!,而后者又会扩展为 panic!。到那时,您的 panic! 就在范围内了。

这个更简单的示例表明,宏会调用 do_foo 恰好在 宏扩展 范围内的任何内容。请注意,甚至没有在宏所在的位置定义 do_foo:

macro_rules! foo {
() => {
do_foo()
};
}

fn main() {
{
fn do_foo() {
println!("1")
}
foo!();
}
{
fn do_foo() {
println!("2")
}
foo!();
}
}

相反,您需要通过其完整路径引用原始宏(自 Rust 1.30 起可用):

macro_rules! panic {
($($args:tt)+) => {{
std::panic!("{}\n --> {}:{}:{}", format_args!($($args)*), file!(), line!(), column!());
}};
}

另见:

关于macros - 我可以用我自己的自定义宏覆盖标准库中的宏吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45864495/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com