1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
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_visit = s.each(|bind| { quote! { ::rustc_middle::ty::fold::TypeFoldable::visit_with(#bind, __folder)?; } }); s.bind_with(|_| synstructure::BindStyle::Move); let body_fold = s.each_variant(|vi| { let bindings = vi.bindings(); vi.construct(|_, index| { let bind = &bindings[index]; quote! { ::rustc_middle::ty::fold::TypeFoldable::fold_with(#bind, __folder) } }) }); s.bound_impl( quote!(::rustc_middle::ty::fold::TypeFoldable<'tcx>), quote! { fn super_fold_with<__F: ::rustc_middle::ty::fold::TypeFolder<'tcx>>( self, __folder: &mut __F ) -> Self { match self { #body_fold } } fn super_visit_with<__F: ::rustc_middle::ty::fold::TypeVisitor<'tcx>>( &self, __folder: &mut __F ) -> ::std::ops::ControlFlow<__F::BreakTy> { match *self { #body_visit } ::std::ops::ControlFlow::CONTINUE } }, ) }