1use proc_macro::{TokenStream};
2use quote::{quote, ToTokens};
3use syn::{parse_macro_input, DeriveInput};
4
5#[proc_macro_derive(Rebindable)]
6pub fn derive_rebindable(input: TokenStream) -> TokenStream {
7 let input = parse_macro_input!(input as DeriveInput);
8
9 let name = input.ident;
10 let generics = input.generics;
11
12 let mut impl_params: Vec<Box<dyn ToTokens>> = vec![Box::new(quote! { 'a })];
13 let mut type_params: Vec<Box<dyn ToTokens>> = vec![];
14 let mut out_params: Vec<Box<dyn ToTokens>> = vec![];
15
16 for _ in generics.lifetimes() {
17 type_params.push(Box::new(quote! { '_ }));
18 out_params.push(Box::new(quote! { 'a }));
19 }
20
21 for ident in generics.type_params().map(|p| &p.ident) {
22 impl_params.push(Box::new(quote! { #ident: 'a }));
23 type_params.push(Box::new(ident.clone()));
24 out_params.push(Box::new(ident.clone()));
25 }
26
27 for param in generics.const_params() {
28 let ident = ¶m.ident;
29 let ty = ¶m.ty;
30 impl_params.push(Box::new(quote! { const #ident: #ty }));
31 type_params.push(Box::new(ident.clone()));
32 out_params.push(Box::new(ident.clone()));
33 }
34
35 TokenStream::from(quote! {
36 unsafe impl<#(#impl_params),*> escher::RebindTo<'a> for #name<#(#type_params),*> {
37 type Out = #name<#(#out_params),*>;
38 }
39 })
40}