compilation_guard/
lib.rs

1use proc_macro::{self, TokenStream};
2
3/// Forces compilation to fail.
4/// 
5/// e.g. 
6/// ```rust
7/// #![allow(unused_imports, dead_code)]
8/// 
9/// use compilation_guard::compilation_guard;
10/// #[cfg_attr(all(unstable, feature = "enable-macro"), derive(VeryExpensiveMacro))]
11/// #[cfg_attr(all(not(unstable), feature = "enable-macro"), compilation_guard("lol"))]
12/// struct A;
13/// 
14/// fn main() {
15/// 
16/// }
17/// ```
18/// 
19/// If you don't enable the unstable flag, you get this.
20/// ```
21/// error: custom attribute panicked
22///  --> src/main.rs:5:58
23///   |
24/// 5 | #[cfg_attr(all(not(unstable), feature = "enable-macro"), compilation_guard("lol"))]
25///   |                                                          ^^^^^^^^^^^^^^^^^^^^^^^^
26///   |
27///   = help: message: Compilation guard was triggered!
28///           lol
29/// ```
30/// 
31#[proc_macro_attribute]
32pub fn compilation_guard(input: TokenStream, _: TokenStream) -> TokenStream {
33    panic_logic(input);
34    unreachable!()
35}
36
37fn panic_logic(input: TokenStream) {
38    let mut iter = input.into_iter();
39    match (iter.next(), iter.next()) {
40        (Some(proc_macro::TokenTree::Literal(literal)), None) => {
41            let s = literal.to_string();
42            let s = format!("Compilation guard was triggered!\n{}", &s[1..s.len()-1]);
43            panic!("{s}");
44        }
45        _ => panic!("This macro is expected to receive a `literal` as an argument.")
46    }
47}