]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_macros/src/lift.rs
Rollup merge of #106811 - khuey:dwp_extension, r=davidtwco
[rust.git] / compiler / rustc_macros / src / lift.rs
1 use quote::quote;
2 use syn::{self, parse_quote};
3
4 pub 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         // Replace `'tcx` lifetime by the `'__lifted` lifetime
16         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(
43         quote!(::rustc_middle::ty::Lift<'__lifted>),
44         quote! {
45             type Lifted = #lifted;
46
47             fn lift_to_tcx(self, __tcx: ::rustc_middle::ty::TyCtxt<'__lifted>) -> Option<#lifted> {
48                 Some(match self { #body })
49             }
50         },
51     )
52 }