2017-08-24 77 views
3

我正在研究一个过程宏,并且我发现编译器在程序宏恐慌时不提供有关proc宏包的信息。我试图重写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; 

,但它不工作。

+0

@kennytm谢谢。但它说同样的事情......并且' //在这里可见:'m1'。 macro_rules! m3 //这里可以看到:'m1','m3'。 '意味着'恐慌!'不应该从'std_panic!'看到(编辑:固定错字,我预计输入为
) – kdy

回答

4

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

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

没有办法,我知道的热切扩大std_panicpanic!

参见:

+0

谢谢你的详细解释。我改变了宏的名字以失败,并且忽略了'unreachble!'和'unimplemented!'。我对此感到满意。可见性是在扩展后从使用地点计算出来的。这说得通 – kdy

相关问题