]>
Commit | Line | Data |
---|---|---|
064997fb | 1 | use quote::quote; |
353b0b11 | 2 | use syn::parse_quote; |
064997fb FG |
3 | |
4 | pub fn type_visitable_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 | ||
9ffffee4 FG |
9 | // ignore fields with #[type_visitable(ignore)] |
10 | s.filter(|bi| { | |
353b0b11 FG |
11 | let mut ignored = false; |
12 | ||
13 | bi.ast().attrs.iter().for_each(|attr| { | |
14 | if !attr.path().is_ident("type_visitable") { | |
15 | return; | |
16 | } | |
17 | let _ = attr.parse_nested_meta(|nested| { | |
18 | if nested.path.is_ident("ignore") { | |
19 | ignored = true; | |
20 | } | |
21 | Ok(()) | |
22 | }); | |
23 | }); | |
24 | ||
25 | !ignored | |
9ffffee4 FG |
26 | }); |
27 | ||
064997fb FG |
28 | if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { |
29 | s.add_impl_generic(parse_quote! { 'tcx }); | |
30 | } | |
31 | ||
32 | s.add_bounds(synstructure::AddBounds::Generics); | |
33 | let body_visit = s.each(|bind| { | |
34 | quote! { | |
35 | ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)?; | |
36 | } | |
37 | }); | |
38 | s.bind_with(|_| synstructure::BindStyle::Move); | |
39 | ||
40 | s.bound_impl( | |
9ffffee4 | 41 | quote!(::rustc_middle::ty::visit::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>), |
064997fb | 42 | quote! { |
9ffffee4 | 43 | fn visit_with<__V: ::rustc_middle::ty::visit::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>( |
064997fb FG |
44 | &self, |
45 | __visitor: &mut __V | |
46 | ) -> ::std::ops::ControlFlow<__V::BreakTy> { | |
47 | match *self { #body_visit } | |
9c376795 | 48 | ::std::ops::ControlFlow::Continue(()) |
064997fb FG |
49 | } |
50 | }, | |
51 | ) | |
52 | } |