Create TypeFoldable derive proc-macro.

This commit is contained in:
Camille GILLOT 2019-11-13 20:47:41 +01:00
parent 695fe96517
commit 9e28e9c545
2 changed files with 41 additions and 0 deletions

View File

@ -9,6 +9,7 @@ use synstructure::decl_derive;
use proc_macro::TokenStream;
mod hash_stable;
mod type_foldable;
mod query;
mod symbols;
@ -23,3 +24,4 @@ pub fn symbols(input: TokenStream) -> TokenStream {
}
decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_foldable_derive);

View File

@ -0,0 +1,39 @@
use synstructure;
use syn;
use quote::quote;
pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
if let syn::Data::Union(_) = s.ast().data {
panic!("cannot derive on union")
}
s.add_bounds(synstructure::AddBounds::Generics);
let body_fold = s.each_variant(|vi| {
let bindings = vi.bindings();
vi.construct(|_, index| {
let bind = &bindings[index];
quote!{
::rustc::ty::fold::TypeFoldable::fold_with(#bind, __folder)
}
})
});
let body_visit = s.fold(false, |acc, bind| {
quote!{ #acc || ::rustc::ty::fold::TypeFoldable::visit_with(#bind, __folder) }
});
s.bound_impl(quote!(::rustc::ty::fold::TypeFoldable<'tcx>), quote!{
fn super_fold_with<__F: ::rustc::ty::fold::TypeFolder<'tcx>>(
&self,
__folder: &mut __F
) -> Self {
match *self { #body_fold }
}
fn super_visit_with<__F: ::rustc::ty::fold::TypeVisitor<'tcx>>(
&self,
__folder: &mut __F
) -> bool {
match *self { #body_visit }
}
})
}