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

时间:2017-08-24 14:39:23

标签: macros rust

我正在处理一个程序宏,我发现编译器在程序宏发生恐慌时没有提供有关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 editionpanic!无法看到我自己的std_panic!,因此应使用标准库中的panic!

我也试过

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

但它没有用。

1 个答案:

答案 0 :(得分: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!(); } }

panic!

我没有办法急切地扩展std_panic class myTabBarController: UITabBarController { override func viewDidLoad() { UITabBar.appearance().backgroundImage = UIImage(named: "secretTab.png") } 内部的 class myTabBarController: UITabBarController { override func viewDidLoad() { self.tabBar.clipsToBounds = true self.tabBarController?.tabBar.autoresizesSubviews = false UITabBar.appearance().backgroundImage = UIImage(named: "secretTab.png") }

另见: