| 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); |
| s.underscore_const(true); |
| |
| 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>) -> Option<#lifted> { |
| Some(match self { #body }) |
| } |
| }) |
| } |