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 })
|
|
}
|
|
},
|
|
)
|
|
}
|