blob: ad7ac74041749075dcf8b118dc2715a936dd82e4 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
use quote::quote;
use syn::{self, parse_quote};
pub fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
s.add_bounds(synstructure::AddBounds::Generics);
s.bind_with(|_| synstructure::BindStyle::Move);
let tcx: syn::Lifetime = parse_quote!('tcx);
let newtcx: syn::GenericParam = parse_quote!('__lifted);
let lifted = {
let ast = s.ast();
let ident = &ast.ident;
// Replace `'tcx` lifetime by the `'__lifted` lifetime
let (_, generics, _) = ast.generics.split_for_impl();
let mut generics: syn::AngleBracketedGenericArguments = syn::parse_quote! { #generics };
for arg in generics.args.iter_mut() {
match arg {
syn::GenericArgument::Lifetime(l) if *l == tcx => {
*arg = parse_quote!('__lifted);
}
syn::GenericArgument::Type(t) => {
*arg = syn::parse_quote! { #t::Lifted };
}
_ => {}
}
}
quote! { #ident #generics }
};
let body = s.each_variant(|vi| {
let bindings = &vi.bindings();
vi.construct(|_, index| {
let bi = &bindings[index];
quote! { __tcx.lift(#bi)? }
})
});
s.add_impl_generic(newtcx);
s.bound_impl(
quote!(::rustc_middle::ty::Lift<'__lifted>),
quote! {
type Lifted = #lifted;
fn lift_to_tcx(self, __tcx: ::rustc_middle::ty::TyCtxt<'__lifted>) -> Option<#lifted> {
Some(match self { #body })
}
},
)
}
|