single_trait_impl/
lib.rs

1use proc_macro_error2::abort;
2use quote::quote;
3use syn::spanned::Spanned as _;
4
5#[proc_macro_error2::proc_macro_error]
6#[proc_macro_attribute]
7pub fn single_trait_impl(
8    _args: proc_macro::TokenStream,
9    input: proc_macro::TokenStream,
10) -> proc_macro::TokenStream {
11    let root_impl = syn::parse_macro_input!(input as syn::ItemImpl);
12    let root_span = root_impl.span();
13    let trait_ = match &root_impl.trait_ {
14        Some((_, path, _)) => path,
15        None => abort!(root_span, "this only works on trait impls"),
16    };
17
18    let mut trait_functions = Vec::with_capacity(root_impl.items.len());
19    for item in &root_impl.items {
20        let mut method = match item {
21            syn::ImplItem::Method(m) => m.clone(),
22            _ => abort!(item, "unsupported item"),
23        };
24
25        method.block.stmts = vec![syn::Stmt::Item(syn::Item::Verbatim(quote! {;}))];
26
27        trait_functions.push(method);
28    }
29
30    proc_macro::TokenStream::from(quote! {
31        pub trait #trait_ {
32            #(#trait_functions)*
33        }
34
35        #root_impl
36    })
37}