rustc_macros/
lift.rs
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 s.underscore_const(true);
8
9 let tcx: syn::Lifetime = parse_quote!('tcx);
10 let newtcx: syn::GenericParam = parse_quote!('__lifted);
11
12 let lifted = {
13 let ast = s.ast();
14 let ident = &ast.ident;
15
16 let (_, generics, _) = ast.generics.split_for_impl();
18 let mut generics: syn::AngleBracketedGenericArguments = syn::parse_quote! { #generics };
19 for arg in generics.args.iter_mut() {
20 match arg {
21 syn::GenericArgument::Lifetime(l) if *l == tcx => {
22 *arg = parse_quote!('__lifted);
23 }
24 syn::GenericArgument::Type(t) => {
25 *arg = syn::parse_quote! { #t::Lifted };
26 }
27 _ => {}
28 }
29 }
30
31 quote! { #ident #generics }
32 };
33
34 let body = s.each_variant(|vi| {
35 let bindings = &vi.bindings();
36 vi.construct(|_, index| {
37 let bi = &bindings[index];
38 quote! { __tcx.lift(#bi)? }
39 })
40 });
41
42 s.add_impl_generic(newtcx);
43 s.bound_impl(quote!(::rustc_middle::ty::Lift<::rustc_middle::ty::TyCtxt<'__lifted>>), quote! {
44 type Lifted = #lifted;
45
46 fn lift_to_interner(self, __tcx: ::rustc_middle::ty::TyCtxt<'__lifted>) -> Option<#lifted> {
47 Some(match self { #body })
48 }
49 })
50}