aboutsummaryrefslogtreecommitdiff
path: root/proc-macro-error/proc-macro-error-attr/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'proc-macro-error/proc-macro-error-attr/src/lib.rs')
-rw-r--r--proc-macro-error/proc-macro-error-attr/src/lib.rs162
1 files changed, 0 insertions, 162 deletions
diff --git a/proc-macro-error/proc-macro-error-attr/src/lib.rs b/proc-macro-error/proc-macro-error-attr/src/lib.rs
deleted file mode 100644
index 3c1013b..0000000
--- a/proc-macro-error/proc-macro-error-attr/src/lib.rs
+++ /dev/null
@@ -1,162 +0,0 @@
-extern crate proc_macro;
-
-use proc_macro::TokenStream;
-use proc_macro2::Ident;
-use quote::quote;
-use std::iter::FromIterator;
-use syn::{
- parse::{Parse, ParseStream},
- parse_macro_input,
- punctuated::Punctuated,
- Attribute, Token,
-};
-use syn_mid::{Block, ItemFn};
-
-use self::Setting::*;
-
-#[proc_macro_attribute]
-pub fn proc_macro_error(attr: TokenStream, input: TokenStream) -> TokenStream {
- let input = parse_macro_input!(input as ItemFn);
- let mut settings = match syn::parse::<Settings>(attr) {
- Ok(settings) => settings,
- Err(err) => {
- let err = err.to_compile_error();
- return quote!(#input #err).into();
- }
- };
-
- let is_proc_macro = is_proc_macro(&input.attrs);
- if is_proc_macro {
- settings.set(AssertUnwindSafe);
- }
-
- if detect_proc_macro_hack(&input.attrs) {
- settings.set(ProcMacroHack);
- }
-
- if !(settings.is_set(AllowNotMacro) || is_proc_macro) {
- return quote!(
- #input
- compile_error!("#[proc_macro_error] attribute can be used only with a proc-macro\n\n \
- hint: if you are really sure that #[proc_macro_error] should be applied \
- to this exact function use #[proc_macro_error(allow_not_macro)]\n");
- )
- .into();
- }
-
- let ItemFn {
- attrs,
- vis,
- constness,
- asyncness,
- unsafety,
- abi,
- fn_token,
- ident,
- generics,
- inputs,
- output,
- block,
- ..
- } = input;
-
- let body = gen_body(block, settings);
-
- quote!(
- #(#attrs)*
- #vis
- #constness
- #asyncness
- #unsafety
- #abi
- #fn_token
- #ident
- #generics
- (#inputs)
- #output
-
- { #body }
- )
- .into()
-}
-
-#[derive(PartialEq)]
-enum Setting {
- AssertUnwindSafe,
- AllowNotMacro,
- ProcMacroHack,
-}
-
-impl Parse for Setting {
- fn parse(input: ParseStream) -> syn::Result<Self> {
- let ident: Ident = input.parse()?;
- match &*ident.to_string() {
- "assert_unwind_safe" => Ok(AssertUnwindSafe),
- "allow_not_macro" => Ok(AllowNotMacro),
- "proc_macro_hack" => Ok(ProcMacroHack),
- _ => Err(syn::Error::new(
- ident.span(),
- format!(
- "unknown setting `{}`, expected one of \
- `assert_unwind_safe`, `allow_not_macro`, `proc_macro_hack`",
- ident
- ),
- )),
- }
- }
-}
-
-struct Settings(Vec<Setting>);
-impl Parse for Settings {
- fn parse(input: ParseStream) -> syn::Result<Self> {
- let punct = Punctuated::<Setting, Token![,]>::parse_terminated(input)?;
- Ok(Settings(Vec::from_iter(punct)))
- }
-}
-
-impl Settings {
- fn is_set(&self, setting: Setting) -> bool {
- self.0.iter().any(|s| *s == setting)
- }
-
- fn set(&mut self, setting: Setting) {
- self.0.push(setting)
- }
-}
-
-#[rustversion::since(1.37)]
-fn gen_body(block: Block, settings: Settings) -> proc_macro2::TokenStream {
- let is_proc_macro_hack = settings.is_set(ProcMacroHack);
- let closure = if settings.is_set(AssertUnwindSafe) {
- quote!(::std::panic::AssertUnwindSafe(|| #block ))
- } else {
- quote!(|| #block)
- };
-
- quote!( ::proc_macro_error::entry_point(#closure, #is_proc_macro_hack) )
-}
-
-// FIXME:
-// proc_macro::TokenStream does not implement UnwindSafe until 1.37.0.
-// Considering this is the closure's return type the unwind safety check would fail
-// for virtually every closure possible, the check is meaningless.
-#[rustversion::before(1.37)]
-fn gen_body(block: Block, settings: Settings) -> proc_macro2::TokenStream {
- let is_proc_macro_hack = settings.is_set(ProcMacroHack);
- let closure = quote!(::std::panic::AssertUnwindSafe(|| #block ));
- quote!( ::proc_macro_error::entry_point(#closure, #is_proc_macro_hack) )
-}
-
-fn detect_proc_macro_hack(attrs: &[Attribute]) -> bool {
- attrs
- .iter()
- .any(|attr| attr.path.is_ident("proc_macro_hack"))
-}
-
-fn is_proc_macro(attrs: &[Attribute]) -> bool {
- attrs.iter().any(|attr| {
- attr.path.is_ident("proc_macro")
- || attr.path.is_ident("proc_macro_derive")
- || attr.path.is_ident("proc_macro_attribute")
- })
-}