| use quote::quote; | |
| use syn::parse_quote; | |
| pub(super) 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<::rustc_middle::ty::TyCtxt<'__lifted>>), | |
| quote! { | |
| type Lifted = #lifted; | |
| fn lift_to_interner(self, __tcx: ::rustc_middle::ty::TyCtxt<'__lifted>) -> #lifted { | |
| match self { #body } | |
| } | |
| }, | |
| ) | |
| } |