flux_macros/
fold.rs

1use quote::quote;
2// use syn::parse_quote;
3
4pub(crate) 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.type_params().any(|ty| ty.ident == "I") {
10    //     s.add_impl_generic(parse_quote! { I });
11    // }
12
13    // s.add_where_predicate(parse_quote! { I: Interner });
14    s.add_bounds(synstructure::AddBounds::Fields);
15    s.bind_with(|_| synstructure::BindStyle::Move);
16    let body_fold = s.each_variant(|vi| {
17        let bindings = vi.bindings();
18        vi.construct(|_, index| {
19            let bind = &bindings[index];
20            quote! {
21                ::flux_middle::rty::fold::TypeFoldable::try_fold_with(#bind, __folder)?
22            }
23        })
24    });
25
26    s.bound_impl(
27        quote!(::flux_middle::rty::fold::TypeFoldable),
28        quote! {
29            fn try_fold_with<__F: ::flux_middle::rty::fold::FallibleTypeFolder>(
30                // self,
31                &self,
32                __folder: &mut __F
33            ) -> Result<Self, __F::Error> {
34                Ok(match self { #body_fold })
35            }
36        },
37    )
38}
39
40pub(crate) fn type_visitable_derive(
41    mut s: synstructure::Structure<'_>,
42) -> proc_macro2::TokenStream {
43    if let syn::Data::Union(_) = s.ast().data {
44        panic!("cannot derive on union")
45    }
46
47    // if !s.ast().generics.type_params().any(|ty| ty.ident == "I") {
48    //     s.add_impl_generic(parse_quote! { I });
49    // }
50
51    // s.add_where_predicate(parse_quote! { I: Interner });
52    s.add_bounds(synstructure::AddBounds::Fields);
53    let body_visit = s.each(|bind| {
54        quote! {
55            ::flux_middle::rty::fold::TypeVisitable::visit_with(#bind, __visitor)?;
56        }
57    });
58    s.bind_with(|_| synstructure::BindStyle::Move);
59
60    s.bound_impl(
61        quote!(::flux_middle::rty::fold::TypeVisitable),
62        quote! {
63            fn visit_with<__V: ::flux_middle::rty::fold::TypeVisitor>(
64                &self,
65                __visitor: &mut __V
66            ) -> ::core::ops::ControlFlow<__V::BreakTy> {
67                match *self { #body_visit }
68                ::core::ops::ControlFlow::Continue(())
69            }
70        },
71    )
72}