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