1 use quote::quote; 2 type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream3pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { 4 if let syn::Data::Union(_) = s.ast().data { 5 panic!("cannot derive on union") 6 } 7 8 s.add_bounds(synstructure::AddBounds::Generics); 9 let body_visit = s.each(|bind| { 10 quote! { 11 ::rustc_middle::ty::fold::TypeFoldable::visit_with(#bind, __folder)?; 12 } 13 }); 14 s.bind_with(|_| synstructure::BindStyle::Move); 15 let body_fold = s.each_variant(|vi| { 16 let bindings = vi.bindings(); 17 vi.construct(|_, index| { 18 let bind = &bindings[index]; 19 quote! { 20 ::rustc_middle::ty::fold::TypeFoldable::fold_with(#bind, __folder) 21 } 22 }) 23 }); 24 25 s.bound_impl( 26 quote!(::rustc_middle::ty::fold::TypeFoldable<'tcx>), 27 quote! { 28 fn super_fold_with<__F: ::rustc_middle::ty::fold::TypeFolder<'tcx>>( 29 self, 30 __folder: &mut __F 31 ) -> Self { 32 match self { #body_fold } 33 } 34 35 fn super_visit_with<__F: ::rustc_middle::ty::fold::TypeVisitor<'tcx>>( 36 &self, 37 __folder: &mut __F 38 ) -> ::std::ops::ControlFlow<__F::BreakTy> { 39 match *self { #body_visit } 40 ::std::ops::ControlFlow::CONTINUE 41 } 42 }, 43 ) 44 } 45