//@ force-host //@ no-prefer-dynamic #![crate_type = "proc-macro"] extern crate proc_macro; use proc_macro::{Ident, Group, TokenStream, TokenTree as Tt}; // This constant has to be above the ALLOCATING_ALGO_THRESHOLD // constant in inherent_impls_overlap.rs const REPEAT_COUNT: u32 = 501; #[proc_macro] /// Repeats the input many times, while replacing idents /// named "IDENT" with "id_$v", where v is a counter. pub fn repeat_with_idents(input: TokenStream) -> TokenStream { let mut res = Vec::new(); fn visit_stream(res: &mut Vec, stream :TokenStream, v: u32) { let mut stream_iter = stream.into_iter(); while let Some(tt) = stream_iter.next() { match tt { Tt::Group(group) => { let tt = Tt::Group(visit_group(group, v)); res.push(tt); }, Tt::Ident(id) => { let id = if &id.to_string() == "IDENT" { Ident::new(&format!("id_{}", v), id.span()) } else { id }; res.push(Tt::Ident(id)); }, Tt::Punct(p) => { res.push(Tt::Punct(p)); }, Tt::Literal(lit) => { res.push(Tt::Literal(lit)); }, } } } fn visit_group(group :Group, v: u32) -> Group { let mut res = Vec::new(); visit_stream(&mut res, group.stream(), v); let stream = res.into_iter().collect(); let delim = group.delimiter(); Group::new(delim, stream) } for v in 0 .. REPEAT_COUNT { visit_stream(&mut res, input.clone(), v) } res.into_iter().collect() }