implicit_clone_derive/
lib.rs

1use quote::quote;
2
3#[proc_macro_derive(ImplicitClone)]
4pub fn derive_implicit_clone(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
5    let syn::DeriveInput {
6        ident, generics, ..
7    } = syn::parse_macro_input!(item as syn::DeriveInput);
8    let (_impl_generics, ty_generics, where_clause) = generics.split_for_impl();
9    let generics = generics
10        .params
11        .iter()
12        .map(|param| match param {
13            syn::GenericParam::Type(syn::TypeParam {
14                attrs,
15                ident,
16                colon_token: _,
17                bounds,
18                eq_token,
19                default,
20            }) => {
21                let bounds = bounds
22                    .iter()
23                    .map(|bound| quote! { #bound })
24                    .chain(std::iter::once(quote! { ::implicit_clone::ImplicitClone }))
25                    .collect::<Vec<_>>();
26                quote! {
27                    #(#attrs)* #ident: #(#bounds)+* #eq_token #default
28                }
29            }
30            _ => quote! { #param },
31        })
32        .collect::<Vec<_>>();
33    let generics = if generics.is_empty() {
34        quote! {}
35    } else {
36        quote! {
37            <#(#generics),*>
38        }
39    };
40    let res = quote! {
41        impl #generics ::implicit_clone::ImplicitClone for #ident #ty_generics #where_clause {}
42    };
43    res.into()
44}