]> git.lizzy.rs Git - rust.git/blob - src/librustc_macros/src/lift.rs
Rollup merge of #68469 - ollie27:skip_count, r=sfackler
[rust.git] / src / librustc_macros / src / lift.rs
1 use proc_macro2;
2 use quote::quote;
3 use syn::{self, parse_quote};
4 use synstructure;
5
6 pub fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
7     s.add_bounds(synstructure::AddBounds::Generics);
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         // Replace `'tcx` lifetime by the `'__lifted` lifetime
17         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(
44         quote!(::rustc::ty::Lift<'__lifted>),
45         quote! {
46             type Lifted = #lifted;
47
48             fn lift_to_tcx(&self, __tcx: ::rustc::ty::TyCtxt<'__lifted>) -> Option<#lifted> {
49                 Some(match *self { #body })
50             }
51         },
52     )
53 }