#![feature(proc_macro_quote)] extern crate proc_macro; use proc_macro::*; #[proc_macro] pub fn proc_macro_item(input: TokenStream) -> TokenStream { input } #[proc_macro] pub fn proc_macro_rules(_input: TokenStream) -> TokenStream { let id = |s| TokenTree::from(Ident::new(s, Span::mixed_site())); let item_def = id("ItemDef"); let local_def = id("local_def"); let item_use = id("ItemUse"); let local_use = id("local_use"); let mut single_quote = Punct::new('\'', Spacing::Joint); single_quote.set_span(Span::mixed_site()); let label_use: TokenStream = [ TokenTree::from(single_quote), id("label_use"), ].iter().cloned().collect(); let dollar_crate = id("$crate"); quote!( use $dollar_crate::proc_macro_item as _; // OK type A = $dollar_crate::ItemUse; // ERROR struct $item_def; let $local_def = 0; $item_use; // OK $local_use; // ERROR break $label_use; // ERROR ) } #[proc_macro] pub fn with_crate(input: TokenStream) -> TokenStream { let mut input = input.into_iter(); let TokenTree::Ident(mut krate) = input.next().unwrap() else { panic!("missing $crate") }; let TokenTree::Ident(span) = input.next().unwrap() else { panic!("missing span") }; let TokenTree::Ident(ident) = input.next().unwrap() else { panic!("missing ident") }; match (krate.to_string().as_str(), span.to_string().as_str()) { ("$crate", "input") => {}, (_, "input") => krate = Ident::new("$crate", krate.span()), ("$crate", "mixed") => krate.set_span(Span::mixed_site()), (_, "mixed") => krate = Ident::new("$crate", Span::mixed_site()), ("$crate", "call") => krate.set_span(Span::call_site()), (_, "call") => krate = Ident::new("$crate", Span::call_site()), (_, x) => panic!("bad span {}", x), } quote!(use $krate::$ident as _;) } #[proc_macro] pub fn declare_macro(input: TokenStream) -> TokenStream { let mut input = input.into_iter(); let TokenTree::Ident(mut krate) = input.next().unwrap() else { panic!("missing $crate") }; let TokenTree::Ident(span) = input.next().unwrap() else { panic!("missing span") }; let TokenTree::Ident(ident) = input.next().unwrap() else { panic!("missing ident") }; match (krate.to_string().as_str(), span.to_string().as_str()) { ("$crate", "input") => {}, (_, "input") => krate = Ident::new("$crate", krate.span()), ("$crate", "mixed") => krate.set_span(Span::mixed_site()), (_, "mixed") => krate = Ident::new("$crate", Span::mixed_site()), ("$crate", "call") => krate.set_span(Span::call_site()), (_, "call") => krate = Ident::new("$crate", Span::call_site()), (_, x) => panic!("bad span {}", x), } quote!( #[macro_export] macro_rules! $ident { ($$i:ident) => { use $krate::$$i as _; }; } ) }