mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-31 21:16:44 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			53 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			53 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use quote::quote;
 | |
| use syn::{self, parse_quote};
 | |
| 
 | |
| pub fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
 | |
|     s.add_bounds(synstructure::AddBounds::Generics);
 | |
|     s.bind_with(|_| synstructure::BindStyle::Move);
 | |
| 
 | |
|     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<'__lifted>),
 | |
|         quote! {
 | |
|             type Lifted = #lifted;
 | |
| 
 | |
|             fn lift_to_tcx(self, __tcx: ::rustc_middle::ty::TyCtxt<'__lifted>) -> Option<#lifted> {
 | |
|                 Some(match self { #body })
 | |
|             }
 | |
|         },
 | |
|     )
 | |
| }
 | 
