1 // compile-flags: --emit=link
4 #![crate_type = "proc-macro"]
5 #![feature(repr128, proc_macro_hygiene, proc_macro_quote, box_patterns)]
6 #![allow(incomplete_features)]
7 #![allow(clippy::useless_conversion, clippy::uninlined_format_args)]
9 extern crate proc_macro;
13 use proc_macro::TokenStream;
14 use quote::{quote, quote_spanned};
15 use syn::parse_macro_input;
16 use syn::spanned::Spanned;
19 parse_quote, FnArg, ImplItem, ItemImpl, ItemTrait, Lifetime, Pat, PatIdent, PatType, Signature, TraitItem, Type,
22 #[proc_macro_attribute]
23 pub fn dummy(_args: TokenStream, input: TokenStream) -> TokenStream {
27 #[proc_macro_attribute]
28 pub fn fake_async_trait(_args: TokenStream, input: TokenStream) -> TokenStream {
29 let mut item = parse_macro_input!(input as ItemTrait);
30 for inner in &mut item.items {
31 if let TraitItem::Method(method) = inner {
32 let sig = &method.sig;
33 let block = &mut method.default;
34 if let Some(block) = block {
35 let brace = block.brace_token;
37 let my_block = quote_spanned!( brace.span => {
38 // Should not trigger `empty_line_after_outer_attr`
43 *block = parse_quote!(#my_block);
47 TokenStream::from(quote!(#item))
50 #[proc_macro_attribute]
51 pub fn rename_my_lifetimes(_args: TokenStream, input: TokenStream) -> TokenStream {
52 fn make_name(count: usize) -> String {
53 format!("'life{}", count)
56 fn mut_receiver_of(sig: &mut Signature) -> Option<&mut FnArg> {
57 let arg = sig.inputs.first_mut()?;
58 if let FnArg::Typed(PatType { pat, .. }) = arg {
59 if let Pat::Ident(PatIdent { ident, .. }) = &**pat {
69 let mut item = parse_macro_input!(input as ItemImpl);
71 // Look for methods having arbitrary self type taken by &mut ref
72 for inner in &mut item.items {
73 if let ImplItem::Method(method) = inner {
74 if let Some(FnArg::Typed(pat_type)) = mut_receiver_of(&mut method.sig) {
75 if let box Type::Reference(reference) = &mut pat_type.ty {
76 // Target only unnamed lifetimes
77 let name = match &reference.lifetime {
78 Some(lt) if lt.ident == "_" => make_name(elided),
79 None => make_name(elided),
84 // HACK: Syn uses `Span` from the proc_macro2 crate, and does not seem to reexport it.
85 // In order to avoid adding the dependency, get a default span from a non-existent token.
86 // A default span is needed to mark the code as coming from expansion.
87 let span = Star::default().span();
89 // Replace old lifetime with the named one
90 let lifetime = Lifetime::new(&name, span);
91 reference.lifetime = Some(parse_quote!(#lifetime));
93 // Add lifetime to the generics of the method
94 method.sig.generics.params.push(parse_quote!(#lifetime));
100 TokenStream::from(quote!(#item))