Skip to content

Commit 9e28e9c

Browse files
committed
Create TypeFoldable derive proc-macro.
1 parent 695fe96 commit 9e28e9c

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

src/librustc_macros/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use synstructure::decl_derive;
99
use proc_macro::TokenStream;
1010

1111
mod hash_stable;
12+
mod type_foldable;
1213
mod query;
1314
mod symbols;
1415

@@ -23,3 +24,4 @@ pub fn symbols(input: TokenStream) -> TokenStream {
2324
}
2425

2526
decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
27+
decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_foldable_derive);
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use synstructure;
2+
use syn;
3+
use quote::quote;
4+
5+
pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
6+
if let syn::Data::Union(_) = s.ast().data {
7+
panic!("cannot derive on union")
8+
}
9+
10+
s.add_bounds(synstructure::AddBounds::Generics);
11+
let body_fold = s.each_variant(|vi| {
12+
let bindings = vi.bindings();
13+
vi.construct(|_, index| {
14+
let bind = &bindings[index];
15+
quote!{
16+
::rustc::ty::fold::TypeFoldable::fold_with(#bind, __folder)
17+
}
18+
})
19+
});
20+
let body_visit = s.fold(false, |acc, bind| {
21+
quote!{ #acc || ::rustc::ty::fold::TypeFoldable::visit_with(#bind, __folder) }
22+
});
23+
24+
s.bound_impl(quote!(::rustc::ty::fold::TypeFoldable<'tcx>), quote!{
25+
fn super_fold_with<__F: ::rustc::ty::fold::TypeFolder<'tcx>>(
26+
&self,
27+
__folder: &mut __F
28+
) -> Self {
29+
match *self { #body_fold }
30+
}
31+
32+
fn super_visit_with<__F: ::rustc::ty::fold::TypeVisitor<'tcx>>(
33+
&self,
34+
__folder: &mut __F
35+
) -> bool {
36+
match *self { #body_visit }
37+
}
38+
})
39+
}

0 commit comments

Comments
 (0)