]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_macros/src/type_foldable.rs
:arrow_up: rust-analyzer
[rust.git] / compiler / rustc_macros / src / type_foldable.rs
1 use quote::quote;
2 use syn::parse_quote;
3
4 pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
5     if let syn::Data::Union(_) = s.ast().data {
6         panic!("cannot derive on union")
7     }
8
9     if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
10         s.add_impl_generic(parse_quote! { 'tcx });
11     }
12
13     s.add_bounds(synstructure::AddBounds::Generics);
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::try_fold_with(#bind, __folder)?
21             }
22         })
23     });
24
25     s.bound_impl(
26         quote!(::rustc_middle::ty::fold::TypeFoldable<'tcx>),
27         quote! {
28             fn try_fold_with<__F: ::rustc_middle::ty::fold::FallibleTypeFolder<'tcx>>(
29                 self,
30                 __folder: &mut __F
31             ) -> Result<Self, __F::Error> {
32                 Ok(match self { #body_fold })
33             }
34         },
35     )
36 }