]> git.lizzy.rs Git - rust.git/blob - src/librustc_macros/src/lift.rs
Rollup merge of #66789 - eddyb:mir-source-scope-local-data, r=oli-obk
[rust.git] / src / librustc_macros / src / lift.rs
1 use synstructure;
2 use syn::{self, parse_quote};
3 use proc_macro2;
4 use quote::quote;
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(quote!(::rustc::ty::Lift<'__lifted>), quote!{
44         type Lifted = #lifted;
45
46         fn lift_to_tcx(&self, __tcx: ::rustc::ty::TyCtxt<'__lifted>) -> Option<#lifted> {
47             Some(match *self { #body })
48         }
49     })
50 }